我正在尝试使用P / Invoke从c#应用程序调用一些c ++ dll函数。他们的标题是:
void f1(float* a, float* b, long n, float* r);
void f2(float* a, float* b, long n, float*& r);
用法的不同之处在于,f1接收在函数外部创建的数组作为第四个参数,而f2保留内存并填充其内部的数组。我可以使用f1声明
[DllImport("myLib.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void f1(float[] a, float[] b, uint n, float[] r);
并从程序中调用它:
float[] a = new float[] { 1,2,3 };
float[] b = new float[] { 4,5,6 };
uint n = 3;
float[] r = new float[n];
f1(a,b,n,r);
这很有效。
但我不知道如何正确使用f2。我声明了,因此:
[DllImport("myLib.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void f2(float[] a, float[] b, uint n, out float[] r);
当我使用未初始化的数组调用f2时:
float[] r = null;
f2(a,b,n, out r);
当我尝试访问r时抛出System.AccessViolationException。
任何sugestions? 提前谢谢。
答案 0 :(得分:2)
P / Invoke编组程序无法将最后一个参数作为数组处理。在.Net阵列中必须有与之相关的大小,而在C中它们只是内存块。由于marhsaler并不知道阵列的大小,因此它无法处理它。但是,您可以使用IntPtr
[DllImport("myLib.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void f2(float[] a, float[] b, uint n, out IntPtr rPtr);
然后,您可以使用Marshal.Copy:
将数组值从指针中拉出float[] r = new float[size];
Marshal.Copy(rPtr, r, 0, size);
此外,您需要在DLL中进行函数调用,以释放f2
为阵列分配的内存,因为没有任何方法可以释放在C DLL中分配的内存。