我必须调用一个win32 dll函数
int func1(int arg1, unsigned char *arg2, int *arg3);
我把包装好的c#写成
public extern int fuc1(int arg1, out IntPtr arg2, out IntPtr arg3);
arg2 必须分配 2048 字节并将其发送到 win32 dll。我将得到 arg2 和 arg3 作为输出。
我如何在 c# 测试应用程序以及 c# 包装器中声明。我做得对吗?
我必须调用一个win32 dll函数
int func1(int arg1, unsigned char *arg2, int *arg3);
我把包装好的c#写成
public extern int fuc1(int arg1, out IntPtr arg2, out IntPtr arg3);
arg2 必须分配 2048 字节并将其发送到 win32 dll。我将得到 arg2 和 arg3 作为输出。
我如何在 c# 测试应用程序以及 c# 包装器中声明。我做得对吗?
C# 中的字节是无符号的 8 位整数。byte[] 是它们的数组。要获取指向此数组的指针,请使用:
var myArray = new byte[2048];
fixed(byte* arg2 = myArray)
{
// use arg2
}
或者:
var myArray = new byte[2048];
GCHandle pinnedRawData = GCHandle.Alloc(myArray, GCHandleType.Pinned);
try
{
// Get the address of the data array
IntPtr pinnedRawDataPtr = pinnedRawData.AddrOfPinnedObject();
}
finally
{
// must explicitly release
pinnedRawData.Free();
}
或者,如果被调用的函数不会缓存指向数组的指针,您可以简单地执行以下操作:
public static extern int fuc1(int arg1, [In,Out] byte[] arg2, ref int arg3);
var arg1 = 0;
var arg2 = new byte[2048];
int arg3 = 42; // If this value won't be used, you can skip initializing arg3 and mark arg3 as out instead of ref (of course, this is pedantic and extraneous, and C# shouldn't even have 'out' as a keyword)
func1(arg1, arg2, ref arg3);
P/Invoke 将自动固定它。
像这样在 C# 中声明函数:
[DllImport(@"MyDll.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern int func1(
int arg1,
StringBuilder arg2,
out int arg3
);
然后这样称呼它:
int arg1 = ...;
StringBuilder sb = new StringBuilder(2048);
int arg3;
int retVal = func1(arg1, sb, out arg3);
string arg2 = sb.ToString();
请注意,C#IntPtr与 C 不匹配int。您需要 C#int来匹配它,因为IntPtr它与指针大小相同,无论是 32 位还是 64 位。但int始终是 4 个字节。
我假设您的 DLL 使用 cdecl 调用约定。如果您使用 stdcall,则可以进行明显的更改。
我还假设您的数据实际上是文本数据。如果它只是一个普通的旧字节数组,那么代码就更简单了。
[DllImport(@"MyDll.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern int func1(
int arg1,
byte[] arg2,
out int arg3
);
然后调用:
int arg1 = ...;
byte[] arg2 = new byte[2048];
int arg3;
int retVal = func1(arg1, arg2, out arg3);