我正在尝试调用为 c/cpp 编写的力传感器的驱动程序 dll。工作的 Cpp 代码如下所示:
我是随dll一起交付的头文件,结构体是这样定义的
typedef struct
{
DWORD usb_hid_idx;
int open;
char vid_pid[256];
char dev_info[256];
char sn_info[256];
int hw_info;
unsigned char hw_var;
int fw_vers;
} t_DeviceInfo;
我需要调用的函数是这样定义的:
extern "C" DLL_API int Search(t_DeviceInfo *p_dev_info);
在主代码中,我只是创建一个由先前定义的
t_DeviceInfo
结构体组成的数组和指向第一个元素的指针,并使用此指针调用函数 Search
:
t_DeviceInfo deviceInfo[16];
t_DeviceInfo* deviceInfoPtr = &deviceInfo[0];
int ret = search(deviceInfoPtr);
至少在那里,一切都很好。对于 C#,目前看起来像这样:
unsafe public struct t_DeviceInfo
{
long usb_hid_idx;
int open;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
char[] vid_pid;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
char[] dev_info;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
char[] sn_info;
int hw_info;
char hw_var;
int fw_vers;
}
unsafe public class ASTAS
{
[DllImport("ASTAS_DLL.dll")]
public extern static int Search(t_DeviceInfo* devInfPtr);
}
主要是:
t_DeviceInfo[] devInfo = new t_DeviceInfo[16];
但仅此而已。如何将结构数组编组到固定的内存位置并将相应的指针传递给
Search()
?
这里不需要
unsafe
。您也可以删除它。并且您的结构声明不正确。有些类型是错误的。 C++ DWORD
是一个无符号 32 位值。 C# long
是有符号的 64 位值。 C++ unsigned char
是一个无符号 8 位值。 C# char 是 16 位字符。通常 unsigned char
映射到 byte
。
结构应该是:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct t_DeviceInfo
{
uint usb_hid_idx;
int open;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
string vid_pid;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
string dev_info;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
string sn_info;
int hw_info;
byte hw_var;
int fw_vers;
}
函数声明应该是:
[DllImport("ASTAS_DLL.dll")]
public extern static int Search([In] t_DeviceInfo[] devInfPtr);
这假设调用约定是 stdcall。在我看来,它实际上是 cdecl。在这种情况下您需要:
[DllImport("ASTAS_DLL.dll", CallingConvention=CallingConvention.Cdecl)]
public extern static int Search([In] t_DeviceInfo[] devInf);
我使用了
[In]
编组。您可能需要根据语义进行修改,我无法从提供的信息中辨别出这一点。
是否有人设法让ASTAS_DLL.dll与c#一起工作?有从设备获取数据的示例代码吗?