我正在尝试将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(这不起作用)并编组像这样的char数组:
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
string szSerialNo;
但会导致堆栈不平衡。
也许你们中的任何人都知道我还能尝试让dll工作吗?
答案 0 :(得分:1)
我看到以下问题:
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
是正确的。但是,当输入参数应为LPWSTR
时,C ++代码将其声明为LPCWSTR
。您可能想检查此参数的语义。它当然感觉像一个输入参数,在这种情况下,C ++编码器有点草率。