你做错了。
你混淆了指针类型。
通过使用new TempStruct()
,你创建了一个指向 TempStruct
的指针数组。我给你的例子创建了一个TempStruct
数组。看到区别了吗?
现在...TempStruct ** outPtr
应该是TempStruct *** outPtr
(因为你想返回(*
)一个指针(*
)数组(*
)...或者如果你喜欢的话,可以是TempStruct**&
:-)
更改这一行:
someData2[i] = (TempStruct)Marshal.PtrToStructure(Marshal.ReadIntPtr(wskptr), typeof(TempStruct));
因为您必须阅读单指针。
我希望您使用delete删除各种TempStruct并使用。
delete[] ptr;
删除结构体数组的操作符。
完整示例:
C++:
struct TempStruct
{
char* str;
int num;
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;
}
这种写法更加严谨,因为 outPtr
和 size
都不能为 NULL
。参见https://dev59.com/wHRB5IYBdhLWcg3wcm6d#620634。C# 的签名也是一样的。
(* outPtr)[0]
吗?既然你要分配一个指针数组,outPtr
参数不应该是一个 三重 指针(即TempStruct *** outPtr
)吗?当你分配内存时所做的转换掩盖了最后一个错误,永远不要转换new
的结果。 - Some programmer dude