cycloidistic cycloidistic - 22 days ago 5
C# Question

What's the correct way to marshal a const float**?

I'm trying to read an array that's created by pinvoking a dll function from C#. When I print out the array's contents it's actually full of junk.

I suspect this is happening because I am incorrectly marshalling a

const float**
to an
out IntPtr
. How do you properly marshal a
const float**
?

DLL C++ Interface

int Foo(void *objPtr, uint64_t *resultLen, const float **result);


DLL Import Statement

[DllImport("foo.dll", CharSet = CharSet.Auto)]
public static extern int Foo(IntPtr objPtr, out ulong resultLen, out IntPtr result);


Calling Code

IntPtr objPtr = getObj();
IntPtr result;
ulong resultLen;
int output = Foo(objPtr, out resultLen, out result);

lc. lc.
Answer

Because there is no way to tell the marshaler the size of the array ahead of time you will have to copy the array manually. So out IntPtr is correct.

Note you will have a problem with very large arrays. See https://msdn.microsoft.com/en-us/library/hh285054(v=vs.110).aspx and How to get around Marshal.Copy (32bit) length limit? . This snippet will use int as the resulting array length. You will need to figure out what to do in your particular case.

Also note your DLL must be responsible for releasing the memory it allocates. See Release unmanaged memory from managed C# with pointer of it .

IntPtr objPtr = getObj();
IntPtr result;
int resultLen;

// call your external function
int output = Foo(objPtr, out resultLen, out result); 

// create an array to hold the output data
float[] array = new float[resultLen];

// copy the data
Marshal.Copy(result, array, 0, resultLen);

// since the memory was allocated by the DLL only it knows how to free it
// so call the free function exported by the DLL
FreeBufferAfterFoo(result);