سؤال

I'm trying to call some c++ dll functions from c# application using P/Invoke. Their headers are:

void f1(float* a, float* b, long n, float* r);

void f2(float* a, float* b, long n, float*& r);

The difference in the usage is that f1 receives as fourth parameter an array which has been created outside the function while f2 reserves memory and fill the array inside of it. I can use f1 declaring

[DllImport("myLib.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void f1(float[] a, float[] b, uint n, float[] r);

and calling it from program:

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);

This works well.

But I don't know how to use f2 correctly. I declare it, thus:

[DllImport("myLib.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void f2(float[] a, float[] b, uint n, out float[] r);

When I call f2 with the uninitialized array:

float[] r = null;
f2(a,b,n, out r);

A System.AccessViolationException is thrown when I try to access r.

Any sugestions? Thanks in advance.

هل كانت مفيدة؟

المحلول

The P/Invoke marshaler can't handle the last parameter as an array. In .Net arrays have to have a size associated with them, while in C they are just memory blocks. Since the marhsaler doesn't know the size of the array it can't handle it. However you can handle it manually using an IntPtr

[DllImport("myLib.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void f2(float[] a, float[] b, uint n, out IntPtr rPtr);

Then you can pull the array values out of the pointer using Marshal.Copy:

float[] r = new float[size];
Marshal.Copy(rPtr, r, 0, size);

Also you'll need a function call in your DLL to free the memory allocated for the array by f2 since there isn't any way to free memory that was allocated in a C DLL.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top