如何处理C#中的C DLL文件中的复杂结构返回类型

本文关键字:文件 DLL 复杂 返回类型 结构 中的 何处理 处理 | 更新日期: 2023-09-27 17:58:17

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

以下是两个函数签名:

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:''Users''tajensen''Documents''hidapiCS''hidapitest''bin''Debug''hidapitest.vshost.exe".

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

我已经做了一些挖掘,我能找到的唯一东西描述了如何接收非常简单的结构的返回类型(即没有指针,只有int和bools等基本类型)。我真的很感激能对这个问题有更多的了解,因为我知道我想去哪里,但我对这类代码的了解还不够,无法独自深入挖掘。

提前感谢,Toms

如何处理C#中的C DLL文件中的复杂结构返回类型

您的结构看起来不错,没有任何改变其包装的命令行标志。

很可能是因为这条线

#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端管理堆栈的规则。

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

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

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

从以下位置下载二进制文件:http://prdownloads.sourceforge.net/swig/swigwin-3.0.10.zip.

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