I keep getting an AccessViolationException when calling the following from an external C DLL:
short get_device_list(char ***device_list, int *number_of_devices);
I set up a DLLImport declaration as such:
[DLLImport("mydll.dll")]
static public extern short get_device_list([MarshalAs(UnmanagedType.LPArray)] ref string[] devices, ref int number_of_devices);
My C# application code:
{
string[] devices = new string[20];
int i = 0;
short ret = 0;
ret = get_device_list(ref devices, ref i); // I receive the AccessViolation Exception here
// devices[0] = "2255f796e958f7f31a7d2e6b833d2d426c634621" which is correct.
}
Although I receive the exception, the device array gets filled correctly with the 2 UUIDs of the devices connected (and also gets resized to size = 2; i is also 2;).
What is wrong?
PS: After a long research I also tried:
[DLLImport("mydll.dll")]
static public extern short get_device_list(ref IntPtr devices, ref int number_of_devices);
and
{
IntPtr devices = new IntPtr();
int i = 0;
short ret = 0;
ret = get_device_list(ref devices, ref i); // No AccessViolation Exception here
string b = Marshal.PtrToStringAuto(devices); // b = "歀ׄ", which is incorrect
}
but that did not help me.
Thanks in advance!
Is the best way to tackle this. The memory is allocated and owned on the native side of the interface. The trick is how to get at it. Something like this should work.
Your code was using
PtrToStringAutobut that’s going to interpret the data asUTF-16encoded. But your C++ code useschar*which is 8 bit ANSI. So you needPtrToStringAnsi. OK, there’s an assumption here that the encoding is not UTF-8, but that’s a detail I cannot provide. It’s easy enough to adapt this to UTF-8.You should also double check that the native code uses the
stdcallcalling convention and isn’t usingcdecl.