1
votes

I have a dll that I cannot import in my vs2012 c# project. I have used dllImport before but I have never had to use Marshal or pointers before. Lucky me I guess.

This is the code that I currently have. The function being called is fnLDA_GetDevInfo(DEVID *ActiveDevices) DEVID is a normal unsigned integer (#define DEVID unsigned integer)

//Allocate an array big enough to hold the device ids for the number of devices present.
//Call fnLDA_GetDevInfo(DEVID *ActiveDevices), which will fill in the array with the device ids for each connected attenuator
//The function returns an integer, which is the number of devices present on the machine.
[DllImport(DLLLOCATION,CallingConvention = CallingConvention.Cdecl)]
private static extern int fnLDA_GetDevInfo([MarshalAs(UnmanagedType.LPArray)] ref uint[] ActiveDevices);

I call the function in my code this way

uint[] MyDevices;
fnLDA_GetDevInfo(ref MyDevices);

At this point I get an error:

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

Now I'm pretty sure the error occurs because I don't call the pointer right or something.

Any help would be appreciated.

1
Why do you declare it as ref?Medinoc
Because he posted an SO question about it :)Hans Passant

1 Answers

4
votes

You have an extra level of indirection. An array is marshalled as a pointer to the array. When you declare the parameter as ref, again a pointer is passed. Thus your C# code matches uint**. Even so, you cannot use ref with an array type because you cannot expect the unmanaged code to produce a managed array.

Your p/invoke should be:

[DllImport(DLLLOCATION,CallingConvention = CallingConvention.Cdecl)]
private static extern int fnLDA_GetDevInfo([Out] uint[] ActiveDevices);

Note that this function is pretty hard to call. Since the function is not passed the length of the array, it is impossible for the function to avoid running off the end of the array if the array is not long enough. I really hope that you have some way to work out how large the array needs to be ahead of calling this function.

So perhaps you are expected to call it like this:

uint[] MyDevices = new uint[SomeLargeNumberThatYouPresumablyCanProvide];
int len = fnLDA_GetDevInfo(MyDevices);

Or perhaps like this:

int len = fnLDA_GetDevInfo(null);
uint[] MyDevices = new uint[len];
fnLDA_GetDevInfo(MyDevices);

I trust that you'll be able to work the rest out from the documentation for the DLL and/or the example C++ programs that call the DLL.