Как я могу получить доступ к структуре в csharp, которая содержит динамические массивы, из неуправляемой DLL? - PullRequest
4 голосов
/ 24 марта 2012

-В моем коде c у меня есть структура, которая содержит множество массивов неизвестного размера в неуправляемой dll (код c)

-Мне нужны данные , один экземпляр этой структуры перенесен в c #, который я позже отправлю обратно в неуправляемый код c

- мне не нужно манипулировать этими данными, когда они попадают в csharp, только держите их / сохраняйте их некоторое время (так чтоможет оставаться в байтовом массиве).

-Я не хочу использовать ключевое слово «unsafe», так как это большой проект, и это всего лишь один маленький кусочек, и я не хочу так его компилировать.

Я пытался маршалировать его как lpArray, и все выглядит хорошо, но когда я смотрю на содержимое после возвращения на csharp, оно всегда пустое.Этот тип стиля маршалинга работал для меня для динамических массивов различных типов, но не для структуры.

Поиск в Интернете приводит к пустым местам и гораздо более сложным сценариям, чем у меня, но если кто-нибудь видел такую ​​ссылку, пожалуйста, опубликуйте ее здесь, я был бы очень признателен!

- обновить здесь более или менее структуру моего кода:

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

1 Ответ

2 голосов
/ 24 марта 2012

Вы говорите, что коду C # не нужно манипулировать структурой.Это делает решение довольно простой проблемы.Вы можете рассматривать указатель структуры как непрозрачный указатель, то есть IntPtr.

. Прежде всего, вы добавляете новую функцию в свой собственный код:

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

Затем в вашем C #код, который вы называете так:

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

Теперь объявите W_Thread_Connect_NET вот так:

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

И назовите все так:

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

Иконечно, вы захотите добавить еще одну функцию с именем DestroyStruct для освобождения памяти структуры, как только вы закончите с ней.

...