gpt4 book ai didi

c# - 将指针数组从 C++ 返回到 C#

转载 作者:太空狗 更新时间:2023-10-29 20:23:52 25 4
gpt4 key购买 nike

下面我有一段来自 C++ 的代码片段。我需要返回指针数组(指向 TempStruct)。

问题是在 C# 端我只得到一个元素。另一方面,我得到了 AV。

**C++**
extern "C" __declspec(dllexport) void GetResult(TempStruct** outPtr, long *size)
{
*outPtr = (TempStruct*)new TempStruct*[2];

outPtr[0] = new TempStruct("sdf", 123);
outPtr[1] = new TempStruct("abc", 456);

*size = 2;
}

**C#**
[DllImport("test.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern void GetResult(out IntPtr outPtr, out int size);

IntPtr ptr = IntPtr.Zero;
int length;
GetResult(out ptr, out length);

int size = Marshal.SizeOf(typeof(TempStruct));
TempStruct[] someData2 = new TempStruct[length];

for (int i = 0; i < length; i++)
{
IntPtr wskptr = (IntPtr)(ptr.ToInt64() + (size * i));
someData2[i] = (TempStruct)Marshal.PtrToStructure(wskptr, typeof(TempStruct));
}

最佳答案

你做错了。

您正在混合指针类型。

通过使用 new TempStruct(),您可以创建指向 TempStruct 的指针数组。我为您提供的示例创建了一个 TempStruct 数组。看到区别了吗?

现在... TempStruct** outPtr 应该是 TempStruct*** outPtr (因为你想返回 (*) 一个数组(*) 的指针 (*)... 或者 TempStruct**& 如果您愿意的话:-)

改变这一行

someData2[i] = (TempStruct)Marshal.PtrToStructure(Marshal.ReadIntPtr(wskptr), typeof(TempStruct));

因为你必须阅读单指针。

我希望你能删除各种 TempStruct 并使用

delete[] ptr;

用于删除结构数组的运算符。

完整示例:

C++:

struct TempStruct
{
char* str;
int num;

// Note the strdup. You don't know the source of str.
// For example if the source is "Foo", then you can't free it.
// Using strdup solves this problem.
TempStruct(const char *str, int num)
: str(strdup(str)), num(num)
{
}

~TempStruct()
{
free(str);
}
};

extern "C"
{
__declspec(dllexport) void GetResult(TempStruct ***outPtr, int *size)
{
*outPtr = new TempStruct*[2];

(*outPtr)[0] = new TempStruct("sdf", 123);
(*outPtr)[1] = new TempStruct("abc", 456);

*size = 2;
}

__declspec(dllexport) void FreeSomeData(TempStruct **ptr, int size)
{
for (int i = 0; i < size; i++)
{
delete ptr[i];
}

delete[] ptr;
}
}

C#:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1), Serializable]
internal struct TempStruct
{
public string str;
public int num;
}

[DllImport("NativeLibrary.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
static extern void GetResult(out IntPtr outPtr, out int numPtr);

[DllImport("NativeLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
static extern void FreeSomeData(IntPtr ptr, int num);

// C++ will return its TempStruct array in ptr
IntPtr ptr;
int size;

GetResult(out ptr, out size);

TempStruct[] someData2 = new TempStruct[size];

for (int i = 0; i < size; i++)
{
IntPtr ptr2 = Marshal.ReadIntPtr(ptr, i * IntPtr.Size);
someData2[i] = (TempStruct)Marshal.PtrToStructure(ptr2, typeof(TempStruct));
}

// Important! We free the TempStruct allocated by C++. We let the
// C++ do it, because it knows how to do it.
FreeSomeData(ptr, size);

请注意,您不需要在 C# struct 上使用 [Serializable]Pack=1

对于 C++ 更正确:

__declspec(dllexport) void GetResult(TempStruct **&outPtr, int &size)
{
outPtr = new TempStruct*[2];

outPtr[0] = new TempStruct("sdf", 123);
outPtr[1] = new TempStruct("abc", 456);

size = 2;
}

它更正确,因为 outPtrsize 都不能为 NULL。见 https://stackoverflow.com/a/620634/613130 。 C# 签名相同。

关于c# - 将指针数组从 C++ 返回到 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31025082/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com