views:

640

answers:

2

I have the following C++ method :

__declspec(dllexport) void __stdcall getDoubles(int *count, double **values); the method allocates and fills an array of double and sets *count to the size of the array.

The only way i managed to get this to work via pinvoke is :

[System.Runtime.InteropServices.DllImportAttribute("xx.dll")]
 public static extern void getDoubles(ref int count, ref System.IntPtr values);

and usage is :

int count = 0;
IntPtr doubles = new IntPtr();
Nappy.getDoubles(ref count, ref doubles);
double[] dvs = new double[count];
for(int i = 0;i < count;++{
    dvs[i] = (double)Marshal.PtrToStructure(doubles, typeof(System.Double));
    doubles = new IntPtr(doubles.ToInt64()+Marshal.SizeOf(typeof(System.Double)));
}

the values end up in the dvs array. Is there a better way ti do this not invloving pointer arithmetic in a managed language...

A: 

I think you can use

Marshal.Copy( source, destination, 0, size );
Ahmed Said
+1  A: 

You'll need to change the unmanaged method signature so it reads like this:

__declspec(dllexport) void __stdcall getDoubles(SAFEARRAY *array);

Then you should be able to use the following managed version of the function:

[System.Runtime.InteropServices.DllImportAttribute("xx.dll")]
public static extern void getDoubles(
              [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VT_R8)]
              double[] array
);

Of course that you'll also have to rewrite your unmanaged code to work with SAFEARRAYs. More about this topic can be found at MSDN.

One question though, I recall working with ZLib in C# which is able, without any wrapper, to work with byte[] while the unmanaged counterpart is BYTE*, have you tried working directly with double* / double[] ?

arul
I have tried using double [] or ref double directly but that only work for a single level of indirection. there is support for marshalling an array of doubles if you know the size on the managed side.
zohar