Access violation

I keep getting an AccessViolationException when called from an external C DLL:

short get_device_list(char ***device_list, int *number_of_devices);

I created 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 get an exception, the device array is correctly populated with the two UUIDs of the connected devices (and also reduced to size = 2; I also equal 2;).

What's 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 it didn’t help me.

Thanks in advance!

+5
source share
2 answers
[DLLImport("mydll.dll")]
static public extern short get_device_list(out IntPtr devices, 
    out int number_of_devices);

This is the best way to handle this. The memory is allocated and belongs to the inside of the interface. The trick is how to get to it. Something like this should work.

static public string[] getDevices()
{
    IntPtr devices;
    int deviceCount;
    short ret = get_device_list(out devices, out deviceCount);
    //need to test ret in case of error

    string[] result = new string[deviceCount];
    for (int i=0; i<deviceCount; i++)
    {
        IntPtr ptr = (IntPtr)Marshal.PtrToStructure(devices, typeof(IntPtr));
        result[i] = Marshal.PtrToStringAnsi(ptr);
        devices += IntPtr.Size;//move to next element of array
    }
    return result;
}

PtrToStringAuto, UTF-16. ++ char*, 8- ANSI. PtrToStringAnsi. , , UTF-8, , . UTF-8.

, stdcall cdecl.

+3

:

, , .

{
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
}

. . , :

  IntPtr devices = new IntPtr();
  int numDevices = 0;      
  short ret = get_device_list(ref devices, ref numDevices); // No AccessViolation Exception here
  for (int i=0; i<numDevices; i++)
  {
    IntPtr ptrToString = Marshal.ReadIntPtr(devices);
    string deviceString = Marshal.PtrToStringAnsi(ptrToString);
    devices += IntPtr.size;
    Console.WriteLine(deviceString);
  }
+2

All Articles