简体   繁体   中英

How can I access a struct in csharp that contains dynamic arrays, from an unmanaged DLL?

-In my c code I have a struct which contains many unknown sized arrays in an unmanaged dll (c code)

-I need the data of one instance of this struct marshaled over to c# , which I will later on send back to the unmanaged c code

-I do not need to manipulate this data once it gets to csharp, only hold onto it/store it for a while (so it can remain in a byte array).

-I do not want to use the keyword 'unsafe' as it is a big project and this is just one small piece and I don't want to be compiling like that.

I tried marshaling it as a lpArray and everything looks fine but when i look at the contents after coming back to the csharp, it is always empty. This type of marshaling style worked for me for dynamic arrays of various types but not the struct.

Searching the web is drawing blanks and much more complicated scenarios than my own, but if anybody has seen such a link please post it here I would be very greatful!

Thanks.

--update here is more or less the structure of my code:

c#:

[DllImport("mydll.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private static extern int W_Thread_Connect_NET(
    [MarshalAs(UnmanagedType.LPStr, SizeConst = 100)] string IPAddress, 
    int DevicePort,
    [MarshalAs(UnmanagedType.LPArray)] byte[] connectionHandle
);

//and call it like this, with an empty struc to be populated by c (can this be done? it is comming back without the data):
byte[] myStrucParam= new byte[100];
int result = W_Thread_Connect_NET(myStrucParam, myParam1, myParam2, ...);

c:

 typedef struct myStructDef{
     char* myArray1, 
     char* myArray2,
     int myInt1,
     ...
 } mystrucObj, *pMystrucObj;

//method that i am wanting to marshal the struct as a paramter here..
 MYDLL_DLLIMPORT int APIENTRY W_Thread_Connect_NET(pMystrucObj strucReturn_handle, char * IPAddress, int DevicePort, ...)
    {
      //(omitted)
    }

You say that the C# code does not need to manipulate the struct. That makes it a pretty simple problem to solve. You can treat the struct pointer as an opaque pointer, that is an IntPtr .

First of all you add a new function to your native code:

pMystrucObj CreateStruct(void)
{
    pMystrucObj res = malloc(sizeof(*res));
    return res;
}

Then in your C# code you call it like this:

[DllImport("mydll.dll", CallingConvention=CallingConvention.Cdecl)]
private static extern IntPtr CreateStruct();

Now declare W_Thread_Connect_NET like this:

[DllImport("mydll.dll", CallingConvention=CallingConvention.Cdecl)]
private static extern int W_Thread_Connect_NET(
    IntPtr theStructPtr,
    string IPAddress, 
    int DevicePort,
    ....
);

And call it all like this:

IntPtr theStructPtr = CreateStruct();
int res = W_Thread_Connect_NET(theStructPtr, IPAddress, DevicePort, ...);

And of course you'll want to add another function named DestroyStruct to deallocate the struct's memory once you are done with it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM