由于C#直接访问USB设备的能力较弱,而C++在这方面则强大许多。因此,考虑通过C++实现读写USB设备,C#调用该DLL接口的方式。这个过程中,上网查了一些资料,但是自己动手,仍然会出现这样或者那样的问题,因此,记录下大体步骤,以便后续他人或者自己可以参考。
主要步骤如下:
1 C++ dll声明导出函数,代码如下(注意不同语言之间由于函数调用方式不一致,这里一定要添加 __stdcall):
extern "C" DLL_API int __stdcall Fun1(int type)
{
return 1;
}
extern "C" DLL_API int __stdcall Fun2()
{
return 2;
}
extern "C" DLL_API int __stdcall Fun3(WCHAR* serialNO)
{
wcscpy(serialNO,L"1234656-245奥迪");
return 3;
}
2 C++ Dll 编写模块定义文件,使得函数名称不会因为C++的函数名称修饰而改变导致找不到函数。
LIBRARY Test.Dll
EXPORTS
Fun1
Fun2
Fun3
3 C++ Dll 工程配置使用def模块定义文件。右键 项目属性-->链接器-->模块定义文件 输入模块定义文件的名称即可。然后编译生成Dll。
4 C# 增加调用声明,类似如下:
public class TEST_DLL_API
{
[DllImport("Test.dll", EntryPoint = "Fun1")]
public static extern int Fun1();
[DllImport("Test.dll", EntryPoint = "Fun1")]
public static extern int Fun2();
[DllImport("Test.dll", EntryPoint = "Fun1")]
public static extern int Fun3(byte[] str);
}
5 如果报DllImport找不到的类似错误,增加 using System.Runtime.InteropServices; 即可解决该问题。
6 调用C#声明C++中的接口,代码如下(注意C++ WCHAR* 与C# 中 string之间的转换方法):
private void button1_Click(object sender, EventArgs e)
{
byte[] serialNo = new byte[64];
int result = 0;
result = TEST_DLL_API.Fun1();
result = TEST_DLL_API.Fun3(serialNo);
result = TEST_DLL_API.Fun2();
string str = Encoding.Unicode.GetString(serialNo);
}
7 运行测试,win7 32位程序应该能够直接成功(把Test.Dll文件拷贝到C#工程bin目录下对应的Debug目录下 bin\Debug)。我是在win7 64位程序调试C#程序,会报 C#调用dll提示"试图加载格式不正确的程序"的错误,解决方法如下:
点击项目属性,生成 属性页,把目标平台Any CPU 设置为 x86 即可( bin\x86\Debug 目录)。
接着把 Test.Dll 文件拷贝到C#工程bin目录下对应的Debug目录下。再次调试运行即大功告成。
8 当然了问题7有更好的解决办法。对于64位系统下调用C++的Dll,可以不设置CPU为x86,我们编译64位的C++ Dll,然后C#使用64位的Dll即可以调试运行。
如果各位在使用过程有其它问题,欢迎讨论。。。