Как передать указатель на массив с помощью p/invoke в С#?
Пример C: подпись API:
void Func(unsigned char* bytes);
В C, когда я хочу передать указатель на массив, я могу сделать:
unsigned char* bytes = new unsigned char[1000];
Func(bytes); // call
Как перевести вышеуказанный API в P/Invoke, чтобы я мог передать указатель на массив байтов С#?
Ответы
Ответ 1
Самый простой способ передать массив байтов - объявить параметр в вашем заявлении import как массив байтов.
[DllImport EntryPoint="func" CharSet=CharSet.Auto, SetLastError=true]
public extern static void Func(byte[]);
byte[] ar = new byte[1000];
Func(ar);
Вы также можете объявить параметр как IntPtr и Marshal данными вручную.
[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);
Ответ 2
Вы можете использовать небезопасный код:
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);
Однако безопасный код будет медленным IMHO.
Ответ 3
Вот соответствующая сигнатура для нативной функции.
[System.Runtime.InteropServices.DllImportAttribute("<Unknown>", EntryPoint="Func")]
public static extern void Func(System.IntPtr bytes) ;