Richard Tyszka Richard Tyszka - 1 year ago 79
C# Question

How can I pass an array from C# to an unmanaged DLL as a long [] and get values back?

I have a C# application that needs to call functions in an unmanaged C DLL. I have it working with various functions, so that setup seems to be all good. I am able to pass a

ref short
to one of the functions and it updates the value in the variable as it should. However, I am running into some issues with a different function that takes a
long []
as input and is supposed to update it to hold a bunch of values about an image. Here is what the function looks like in the .h file:

short GetImage (
short nIndex,
long arrImageParam []

And here is what our C# code looks like when it adds the function:

private delegate short GetImage(short nIndex, int [] arrImageParam);

I'm calling the function like so:

var arrImageParam = new int [20];
short b = GetImage.Invoke(1, arrImageParam);

This does not work - I get the message "unable to read memory" when I try to look at the values in the array in Visual Studio. I assume it is because we are not marshalling correctly.

We also tried making the function like this (using "ref"):

private delegate short GetImage(short nIndex, ref int [] arrImageParam);

And calling it with a ref input:

short c = GetImage.Invoke(1, ref arrImageParam);

which gives an error:

FatalExecutionEngineError' - "Additional information: The runtime has encountered a fatal error. The address of the error was at 0x72cfe248, on thread 0xf4c. The error code is 0xc0000005."

We also tried this below, but it didn't seem to work correctly either - it sets the output array to length of 2 and doesn't seem to get any real values

private delegate short GetImage(short nIndex, ref IntPtr arrImageParam);


int[] array2 = new int[20];
int size = array2.Length;
for (int i = 0; i < array2.Length; i++)
array2[i] = i;
IntPtr buffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(size)
* array2.Length);
Marshal.Copy(array2, 0, buffer, array2.Length);

short c = GetImage.Invoke(1, ref buffer);

int[] arrayRes = new int[size];
Marshal.Copy(buffer, arrayRes, 0, size);
Console.WriteLine("\nInteger array passed ByRef after call:");
foreach (int i in arrayRes)
Console.Write(" " + i);

So, what is the correct way to pass an array into this C DLL function that asks for long[] and get back a filled array?

Answer Source

I managed to get it to return something that I can turn into an array and get the elements from it. Here is how it worked for me:

IntPtr pointer = Marshal.AllocHGlobal(2048);
short b = GetImage.Invoke(imageUploadCounter, pointer);
int[] managedArray = new int[21];
Marshal.Copy(pointer, managedArray, 0, 21);
int imageID = managedArray[10]; 
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download