Return 从 c++ 到 c# 的指针数组
Return array of pointers from c++ to c#
下面是来自 C++ 的代码片段。
我需要 return 指针数组(指向 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
(因为你想要 return (*
) 一个指针数组 (*
) ( *
)... 或者 TempStruct**&
如果您愿意的话:-)
更改此行
someData2[i] = (TempStruct)Marshal.PtrToStructure(Marshal.ReadIntPtr(wskptr), typeof(TempStruct));
因为你必须阅读单指针。
我希望你能删除各种 TempStruct
with delete 并使用
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;
}
更正确,因为outPtr
和size
都不可能是NULL
。参见 。 C# 签名相同。
C++代码有误。它是 returning 指向结构的指针数组。您将值 return 转换为 new
的事实应该提醒您您犯了一个错误。你想要 return 一个结构数组。
应该是:
*outPtr = new TempStruct[2];
(*outPtr)[0].str = "sdf";
(*outPtr)[0].i = 123;
(*outPtr)[1].str = "abc";
(*outPtr)[1].i = 456;
*size = 2;
下面是来自 C++ 的代码片段。 我需要 return 指针数组(指向 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
(因为你想要 return (*
) 一个指针数组 (*
) ( *
)... 或者 TempStruct**&
如果您愿意的话:-)
更改此行
someData2[i] = (TempStruct)Marshal.PtrToStructure(Marshal.ReadIntPtr(wskptr), typeof(TempStruct));
因为你必须阅读单指针。
我希望你能删除各种 TempStruct
with delete 并使用
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;
}
更正确,因为outPtr
和size
都不可能是NULL
。参见 。 C# 签名相同。
C++代码有误。它是 returning 指向结构的指针数组。您将值 return 转换为 new
的事实应该提醒您您犯了一个错误。你想要 return 一个结构数组。
应该是:
*outPtr = new TempStruct[2];
(*outPtr)[0].str = "sdf";
(*outPtr)[0].i = 123;
(*outPtr)[1].str = "abc";
(*outPtr)[1].i = 456;
*size = 2;