P / Invoke Marshaling float *&

时间:2014-04-28 17:20:53

标签: c# pinvoke

我正在尝试使用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? 提前谢谢。

1 个答案:

答案 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中分配的内存。