P/Invoking 从 C++ 到 C# 的 int[] 显示随机大数而不是原始数组成员
P/Invoking int[] from c++ to C# shows random large numbers instead of original array members
我有以下 C++ 代码:
int nCount[5] = {0, 1, 2, 3, 4};
return &nCount[0];
我在 C# P/Invoke 层中收到此代码,代码如下:
[DllImport(@"/sharedlibrary.so",CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr read_array_adapter();
效果很好。但是当我 运行 下面的 c# 代码时:
int[] result = new int[5];
Marshal.Copy(ptr, result, 0, 5);
它用一些随机的大数字填充数组结果,如下所示:
int[]{1663918692,1852139884,1970351988,1936417641,244554078}
这与我在 C++ 中的原始数组无关,它看起来像 {0,1,2,3,4} 知道 Marshal.Copy
可能会做什么来填充这些结果吗?
如果您希望内存在函数范围内存活,并且不想使用全局变量,那么您必须从堆栈(局部变量)以外的其他地方分配它。
你可以使用任何分配器,你可以使用 .NET 已经知道的分配器,或者如果你使用另一个特定于 C++ 或你的平台的分配器,那么你还必须提供另一个 P/Invokable 函数来释放,一些东西像这样:
C++
int* read_array_adapter()
{
int nCount[5] = {0, 1, 2, 3, 4};
return AllocateAndCopy(...);
}
void free_array_adapter(int *) // or a generic pointer of course...
{
Free(...);
}
C#
static void Main(string[] args)
{
var ptr = read_array_adapter();
var result = new int[5];
Marshal.Copy(ptr, result, 0, 5);
free_array_adapter(ptr);
}
[DllImport(@"/sharedlibrary.so",CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr read_array_adapter();
[DllImport(@"/sharedlibrary.so",CallingConvention = CallingConvention.Cdecl)]
public extern static void free_array_adapter(IntPtr ptr);
您还可以在 .NET 和 C/C++ 之间使用已知的分配器,但这取决于平台(Windows、linux 等):https://www.mono-project.com/docs/advanced/pinvoke/
这里是 C 的 malloc/free duo 的示例实现:
int* read_array_adapter()
{
int nCount[5] = { 0, 1, 2, 3, 4 };
int* p = (int*)malloc(5 * 4);
memcpy(p, nCount, 5 * 4);
return p;
}
void free_array_adapter(void * ptr)
{
free(ptr);
}
我有以下 C++ 代码:
int nCount[5] = {0, 1, 2, 3, 4};
return &nCount[0];
我在 C# P/Invoke 层中收到此代码,代码如下:
[DllImport(@"/sharedlibrary.so",CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr read_array_adapter();
效果很好。但是当我 运行 下面的 c# 代码时:
int[] result = new int[5];
Marshal.Copy(ptr, result, 0, 5);
它用一些随机的大数字填充数组结果,如下所示:
int[]{1663918692,1852139884,1970351988,1936417641,244554078}
这与我在 C++ 中的原始数组无关,它看起来像 {0,1,2,3,4} 知道 Marshal.Copy
可能会做什么来填充这些结果吗?
如果您希望内存在函数范围内存活,并且不想使用全局变量,那么您必须从堆栈(局部变量)以外的其他地方分配它。
你可以使用任何分配器,你可以使用 .NET 已经知道的分配器,或者如果你使用另一个特定于 C++ 或你的平台的分配器,那么你还必须提供另一个 P/Invokable 函数来释放,一些东西像这样:
C++
int* read_array_adapter()
{
int nCount[5] = {0, 1, 2, 3, 4};
return AllocateAndCopy(...);
}
void free_array_adapter(int *) // or a generic pointer of course...
{
Free(...);
}
C#
static void Main(string[] args)
{
var ptr = read_array_adapter();
var result = new int[5];
Marshal.Copy(ptr, result, 0, 5);
free_array_adapter(ptr);
}
[DllImport(@"/sharedlibrary.so",CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr read_array_adapter();
[DllImport(@"/sharedlibrary.so",CallingConvention = CallingConvention.Cdecl)]
public extern static void free_array_adapter(IntPtr ptr);
您还可以在 .NET 和 C/C++ 之间使用已知的分配器,但这取决于平台(Windows、linux 等):https://www.mono-project.com/docs/advanced/pinvoke/
这里是 C 的 malloc/free duo 的示例实现:
int* read_array_adapter()
{
int nCount[5] = { 0, 1, 2, 3, 4 };
int* p = (int*)malloc(5 * 4);
memcpy(p, nCount, 5 * 4);
return p;
}
void free_array_adapter(void * ptr)
{
free(ptr);
}