我正在尝试将 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 工作吗?
最佳答案
我看到以下问题:
LRESULT
是指针大小的带符号整数。这是 C# 上的IntPtr
。LONG
是一个扩展为long
的宏。在 Windows 上,C++long
是一个 32 位有符号整数。所以在 C# 端你需要使用int
。- 结构声明错误(见下文)。而且您无法通过引用传递结构。
- 宏
CALLBACK
表示函数是stdcall
。 - 也根本不需要
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/