【问题标题】:DLLImport type problemsDLLImport 类型问题
【发布时间】:2014-03-07 18:12:26
【问题描述】:

我正在尝试将 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 工作?

【问题讨论】:

    标签: c# c++ pinvoke


    【解决方案1】:

    我看到以下问题:

    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++ 编码器有点草率。

    【讨论】:

    • 谢谢你uuuuuuuuuuuuuuuuuuuuuuuuuu,它工作正常:) 现在真的更有意义了。是的,pszMask 是一个输入参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多