一次WPF/C#调用C++ dll库的学习记录
本文开发过程,对接硬件开发,但是只有Demo软件,以及dll函数说明chm文档,没有Demo代码,chm文档里函数太多,且杂乱无章,重复!
确定C++编写的dll库在C#中的类型对应关系
以下是本次学习过程中使用到的一些的对应关系:
C /C++语言类型 | C# 数据类型 |
---|---|
char * 变量名 | StringBuilder 变量名 |
int | int |
long | int |
unsigned char 变量名 | byte 变量名 |
unsigned char * 变量名 | ref byte 变量名 |
HANDLE | System.IntPtr |
unsigned short 变量名 | Int16 变量名 |
short 变量名 | Int16 变量名 |
函数举例,比如:
- 这是一个初始化接口函数
HANDLE USER_API PrinterInit ( short port, int baud )
转成C#后
[DllImport("Demo.dll")]
public static extern IntPtr PrinterInit (Int16 port, int baud);
- 打印机参数获取
int __stdcall PrinterCheck ( unsigned char * FontSize, unsigned char* Alignment, unsigned char* LeftMargin, unsigned char* RightMargin, unsigned char* RowPitch, unsigned char* PrintOutRate )
[DllImport("Demo.dll")]
public static extern int PrinterCheck(ref byte FontSize, ref byte Alignment,
ref byte LeftMargin,ref byte RightMargin, ref byte RowPitch, ref byte PrintOutRate);
- 打印机参数设置
int __stdcall PrinterSet(unsigned char FontSize, unsigned char Alignment,unsigned char LeftMargin, unsigned char RightMargin,unsigned char RowPitch,unsigned char PrintOutRate)
[DllImport("Demo.dll")]
public static extern int PrinterSet(byte FontSize, byte Alignment, byte LeftMargin,
byte RightMargin, byte RowPitch, byte PrintOutRate);
- 读取身份证
long __stdcall ReadIdentityCard ( int iType, char* pOutInfo,int iCreatPhoto = 0 )
[DllImport("Demo.dll", CallingConvention = CallingConvention.Winapi)]
public static extern int ReadIdentityCard (int iType, StringBuilder pOutInfo, int iCreatPhoto);
以上列举的类型对应转换关系,是测试可用的。
确定函数调用
如果开发过程中,第三方提供了SDK和Demo代码,那上面的转换过程就没必要了,现在的前提就是,第三方只提供Demo软件,不给Demo代码,这就麻烦了
c++写的程序,又不能像Androud那样反编译,这时了解到可以通过 ollydbg 软件来得知程序调用了哪些函数,
如上图,可以知道 里面的函数对应哪个操作
知道函数之后,就去函数说明文档里找对应函数,然后按照第一步的对应关系便可转成C#能调用的方法了
一定要注意关系转换正确,很多崩溃错误都是由于这个引起的
问题记录:
- 1、在读取身份信息的时候,
ReadIdentityCard (int iType, StringBuilder pOutInfo, int iCreatPhoto);
要传入StringBuilder 参数
,开始是这样的
string result = "";
result = result.PadLeft(1024 * 4);
StringBuilder sb = new StringBuilder(result);
ReadIdentityCard(1,sb,0);
但是这种方式经常会崩溃,提示 System.AccessViolationException: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
折腾半天之后 改成 StringBuilder sb = new StringBuilder(1024*4);
就可以了,还不明白为什么
- 2、异常崩溃 程序捕获不到的那种。。
身份证 与 打印机不能同时使用,因为是同一传输线
2022-07-15 记录
调用打印机厂商提供的dll库来监测打印机状态,本来按照约定的函数调用,结果提示 【无法在DLL "xxxx.dll"中找到名为“xxxx”的入口函数】,按理正常情况是不会提示这个错误的,就猜测是不是定义函数有误。
这里度娘又告诉我,可以使用windows系统里的工具来查看dll里定义的函数情况。
我使用的是win10下VS2019,使用everything搜 【dumpbin.exe】
如果存在的话,打开路径,然后在该路径下使用cmd命令 【dumpbin.exe /EXPORTS “xxx.dll”】
如下图。
红框里才是dll库里实际的方法函数名,和文档约定的是不一样的,导致调用失败提示 【无法在DLL "xxxx.dll"中找到名为“xxxx”的入口函数】,是真的坑!
![在这里插入图片描述](https://img-blog.csdnimg.cn/76cf7e9297b24eafac9607299b1d26bb.png