如何从C#中的C DLL文件处理复杂的struct返回类型?

时间:2016-07-21 19:02:13

标签: c# c pointers struct marshalling

我一直试图让C库(DLL)使用C#中的一些简单测试代码。到目前为止,我已经能够很好地导入和使用简单的功能。我现在遇到的问题是我不知道如何从这个导入的函数中接收复杂的struct返回类型。

以下是两个功能签名:

C:

#define HID_API_EXPORT __declspec(dllexport)
#define HID_API_CALL

struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id);

C#:

[DllImport("hidapi.dll")]
public static extern hid_device_info hid_enumerate(ushort vendor_id, ushort product_id);

这是两个结构:

C:

struct hid_device_info {
    char *path;
    unsigned short vendor_id;
    unsigned short product_id;
    wchar_t *serial_number;
    unsigned short release_number;
    wchar_t *manufacturer_string;
    wchar_t *product_string;
    unsigned short usage_page;
    unsigned short usage;
    int interface_number;

    struct hid_device_info *next;
};

C#:

[StructLayout(LayoutKind.Sequential)]
public struct hid_device_info
{
    public IntPtr path;
    public ushort vendorid;
    public ushort productid;
    public IntPtr serialnumber;
    public ushort releasenumber;
    public IntPtr manufacturer;
    public IntPtr product;
    public ushort usagepage;
    public ushort usage;
    public int interfacenumber;

    public IntPtr next;
}

我在运行程序时遇到此错误:

  

托管调试助手' PInvokeStackImbalance'已经检测到了   问题   ' C:\用户\ tajensen \文件\ hidapiCS \ hidapitest \ BIN \调试\ hidapitest.vshost.exe'

     

附加信息:调用PInvoke函数   ' hidapiCS hidapiCS.hidapi :: hid_enumerate&#39!;堆栈不平衡。   这可能是因为托管的PInvoke签名不匹配   非托管目标签名。检查调用约定和   PInvoke签名的参数与目标非托管匹配   签名。

我已经做了一些挖掘,我能够找到的唯一的东西描述了如何接收非常简单结构的返回类型(即没有指针,只有基本类型,如整数和布尔) 。我真的很感激这个问题的一些额外见解,因为我知道我想成为什么样的人,但是我对这种代码的了解还不够深入,我自己也可以深入了解。

提前致谢, 汤姆斯

2 个答案:

答案 0 :(得分:2)

您的结构看起来很好,禁止任何更改其打包的命令行标志。

可能,因为这条线

#define HID_API_CALL

这意味着您正在使用默认的调用约定,通常为__cdecl。因此,将P / Invoke定义更改为:

[DllImport("hidapi.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern hid_device_info hid_enumerate(ushort vendor_id, ushort product_id);

因此,正确遵循了如何在C端管理堆栈的规则。

答案 1 :(得分:1)

有一个名为 SWIG 的工具,一个代码生成工具,将用C和C ++编写的程序与各种高级编程语言(如c#)连接起来。它为二十三种不同的目标语言生成包装代码:

它对这些任务非常强大,特别是数据类型/指针转换等等。它节省了手动转换。

尝试使用此工具为您的案例生成C#代码,最后编译Dll。

http://prdownloads.sourceforge.net/swig/swigwin-3.0.10.zip下载二进制文件。

对于教程:http://www.swig.org/tutorial.html