【发布时间】:2013-03-04 16:12:03
【问题描述】:
示例 C API 签名:
void Func(unsigned char* bytes);
在 C 中,当我想传递一个指向数组的指针时,我可以这样做:
unsigned char* bytes = new unsigned char[1000];
Func(bytes); // call
如何将上述 API 转换为 P/Invoke,以便可以将指针传递给 C# 字节数组?
【问题讨论】:
示例 C API 签名:
void Func(unsigned char* bytes);
在 C 中,当我想传递一个指向数组的指针时,我可以这样做:
unsigned char* bytes = new unsigned char[1000];
Func(bytes); // call
如何将上述 API 转换为 P/Invoke,以便可以将指针传递给 C# 字节数组?
【问题讨论】:
你可以使用不安全的代码:
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);
但是,恕我直言,安全代码会很慢。
【讨论】:
这是本机函数的适当签名。
[System.Runtime.InteropServices.DllImportAttribute("<Unknown>", EntryPoint="Func")]
public static extern void Func(System.IntPtr bytes) ;
【讨论】:
传递字节数组的最简单方法是在导入语句中将参数声明为字节数组。
[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);
【讨论】:
Marshal.SizeOf(object) 不适用于数组。我敢肯定,如果您将数组传递给它,您会遇到异常,但我现在没有在我面前打开 VS 来尝试。要正确确定数组的大小,对于您的示例,代码将是 Marshal.SizeOf(typeof(byte)) * ar.Length。