Как я могу передать указатель на массив с помощью p / invoke в C #? - PullRequest
21 голосов
/ 14 ноября 2008

Пример C подписи API:

void Func(unsigned char* bytes);

В C, когда я хочу передать указатель на массив, я могу сделать:

unsigned char* bytes = new unsigned char[1000];
Func(bytes); // call

Как мне перевести вышеуказанный API в P / Invoke, чтобы я мог передать указатель на байтовый массив C #?

Ответы [ 3 ]

34 голосов
/ 14 ноября 2008

Самый простой способ передать массив байтов - объявить параметр в вашем операторе импорта как байтовый массив.

[DllImport EntryPoint="func" CharSet=CharSet.Auto, SetLastError=true]
public extern static void Func(byte[]);

byte[] ar = new byte[1000];
Func(ar);

Вы также должны иметь возможность объявить параметр как IntPtr и маршалировать данные вручную.

[DllImport EntryPoint="func" CharSet=CharSet.Auto, SetLastError=true]
public extern static void Func(IntPtr p);

byte[] ar = new byte[1000];
IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(byte)) * ar.Length);
Marshal.Copy(ar, 0, p, ar.Length);
Func(p);
Marshal.FreeHGlobal(p);
7 голосов
/ 14 ноября 2008

Вы можете использовать небезопасный код:

unsafe 
{
     fixed(byte* pByte = byteArray)
     IntPtr intPtr = new IntPtr((void *) pByte);
     Func(intPtr);
}

Если вам нужно использовать безопасный код, вы можете использовать несколько трюков:

IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(byteArray));
Marshal.Copy(byteArray, 0, intPtr, Marshal.SizeOf(byteArray));

Func(intPtr);

Marshal.FreeHGlobal(intPtr);

Однако безопасный код будет медленным, ИМХО.

3 голосов
/ 14 ноября 2008

Вот соответствующая подпись для встроенной функции.

[System.Runtime.InteropServices.DllImportAttribute("<Unknown>", EntryPoint="Func")]
public static extern  void Func(System.IntPtr bytes) ;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...