c# - DLL导入类型问题

标签 c# c++ pinvoke

我正在尝试将 C DLL 导入到我的 C# 项目中。 .h 代码如下所示:

 _declspec(dllexport)   LRESULT CALLBACK SensFindDeviceW(LONG n, LPWSTR pwszMask, PSENSDEVICEW pDevice);

_SENSDEVICEW 结构:

typedef struct  _SENSDEVICEW
{
    WCHAR       szSerialNo[32];
    WCHAR       szDeviceID[32];
    LONG        nIndex;
} SENSDEVICEW, * PSENSDEVICEW;

所以到目前为止,我在 C# 中所做的就是使用 DLLImport:

[DllImport("dll/UFTAccess.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
    static extern unsafe long SensFindDeviceW(long n, String pszMask, SENSDEVICEW pDevice);

定义一个结构体:

[StructLayout(LayoutKind.Sequential)]
unsafe struct SENSDEVICEW
{
    public char[] szSerialNo;
    public char[] szDeviceID;
    public long nIndex;
}

并尝试在方法中使用它:

SENSDEVICEW myDevice = new SENSDEVICEW();
myDevice.szSerialNo = new char[32];
myDevice.szDeviceID = new char[32];         
        long test =  SensFindDeviceW(1, "", myDevice);

通过此获取 System.Runtime.InteropServices.SafeArrayTypeMismatchException

如果我不初始化数组,我会收到堆栈不平衡错误。

我已经尝试过使用 stringbuilder(它不起作用)并像这样编码字符数组:

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
string szSerialNo;

但这会导致堆栈不平衡。

也许你们中的任何人都知道我还可以尝试让 dll 工作吗?

最佳答案

我看到以下问题:

  1. LRESULT 是指针大小的带符号整数。这是 C# 上的 IntPtr
  2. LONG 是一个扩展为 long 的宏。在 Windows 上,C++ long 是一个 32 位有符号整数。所以在 C# 端你需要使用 int
  3. 结构声明错误(见下文)。而且您无法通过引用传递结构。
  4. CALLBACK表示函数是stdcall
  5. 也根本不需要unsafe。你应该删除它。

代码应该是:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct SENSDEVICEW
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
    public string szSerialNo;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
    public string szDeviceID;
    public int nIndex;
}

[DllImport("...", CallingConvention=CallingConvention.Stdcall, 
    CharSet=CharSet.Unicode)]
static extern IntPtr SensFindDeviceW(int n, string pszMask, 
    ref SENSDEVICEW pDevice);

最后,我假设 pszMask 是一个输入参数。因此 string 是正确的。但是,当输入参数应该是 LPCWSTR 时,C++ 代码将其声明为 LPWSTR。您可能想检查此参数的语义。它确实感觉像是一个输入参数,在这种情况下,C++ 编码器有点马虎。

关于c# - DLL导入类型问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22246868/

相关文章:

android - fragment 着色器未针对 Android 源代码末尾的随机符号进行编译

c# - 带有 std::string 的 PInvoke 自定义编码(marshal)拆收器

c# - 未找到入口点异常

c# - 使用带有内存流的 C# 在控制台应用程序中保存图像时 GDI + 中出现一般错误

c# - 在 MVC Controller 之外使用 Controller.Content c#

c++ - c++标准库的设计原则是什么?

c++ - 将秒数转换为 std::chrono::duration?

windows - 如何找到用户刚刚启动的可执行文件?

C# - WebMethodAttribute 是否会对性能产生不利影响?

c# - 在 Xamarin.Mac 中注册服务