将 C++ int* 编组为 C#
Posted
技术标签:
【中文标题】将 C++ int* 编组为 C#【英文标题】:Marshaling C++ int* to C# 【发布时间】:2010-12-06 04:15:40 【问题描述】:我正在尝试让 dll 工作。
DLL 是用 C++ 编写的,它需要将 int* 传递给 C#。我花了几天的时间来让它工作,但它失败了。我开始拔头发,因为我不知道出了什么问题。我已经尝试了一切。我对 C++ 不像对 C# 那样熟悉,所以问题可能来自那里......
从 dll 中读取正常,但返回的值不正确。我删除了输入,我只是想通过一个测试数组。我在 C++ 中使用的函数是:
extern "C" EAGLE128DLL_API int* encryptFunc()
//return encrypt(x, Q);
int t[128];
for(int i = 0; i < 128; i++)
t[i] = 5;
return t;
;
我用来调用这个函数的C#代码如下:
[DllImport("C:\\Users\\Leon\\Documents\\Visual Studio 2010\\Projects\\Eagle128DLL\\Release\\Eagle128DLL.dll")]
public static extern IntPtr encryptFunc();
...
IntPtr outputPtr = encryptFunc();
int[] output = new int[128];
Marshal.Copy(outputPtr, output, 0, 128);
输出数组中的值应该全是 5。但我得到的是: 16187392、16190224..etc(不是 5 的)
【问题讨论】:
您还应该能够使用 [return: MarshalAs] 属性返回 int[] 而不是 IntPtr 并让编组器为您完成工作: [return: MarshalAs(UnmanagedType.LPArray , SizeConst = 128)] public static extern int[] encryptFunc(); 【参考方案1】:C++ 代码包含一个错误:您正在返回一个指向存储在堆栈中的变量的指针(t[128]
只是一个临时变量),这将不起作用。只要您的 encryptFunc
返回,call stack will be unwound 和变量 t[128]
就会被丢弃。
如果您的代码不需要可重入或线程安全,您可以简单地将t[128]
设为静态:
static int t[128];
...
return t;
静态变量将不再存储在堆栈中,并将在函数结束后继续存在。
【讨论】:
哈哈简直不敢相信这么简单。最大的拔毛器总是如此简单,以至于一个人都不会想到它......非常感谢! 我猜我应该在静态数组上使用 delete[] 来将它们从内存中删除? 不,不要那样做。仅在已在堆上分配的内存上使用 delete[](使用 new)。您应该不需要删除静态变量。【参考方案2】:我认为您的问题是您试图返回一个已在 C 函数的堆栈上本地声明的值。
最好的办法是将一个预先分配的数组传递给您的 C 函数,该函数将接收该函数创建的数据并将其返回给调用者。
【讨论】:
以上是关于将 C++ int* 编组为 C#的主要内容,如果未能解决你的问题,请参考以下文章