最近做一个读市民卡的项目,读卡器公司提供的读市民卡dll是用C++写的。

下面记录一些自己的心得,供需要的朋友参考。

声明dll函数要加上stdcall关键字,否则可能会报地址非法的错误。

代码:

unit cMain;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, DB, ADODB, StdCtrls, ComCtrls,ActiveX, ExtCtrls;typeTForm1 = class(TForm)btnReadICard: TButton;Memo1: TMemo;      procedure btnReadICardClick(Sender: TObject);private{ Private declarations }public{ Public declarations }end;
//2014-12-11
typePICC_CONFIG=^ICC_CONFIG;ICC_CONFIG=recordport:Integer;baud:Integer;timeout:Integer;PSAMSlot:Integer;ICCSlot:Integer;end;//  ICC_CONFIG=record
//        port:Cardinal;
//        baud:Cardinal;
//        timeout:Cardinal;
//        PSAMSlot:longword;
//        ICCSlot:longword;
//    end;//2014-12-11function  SIReaderInit(icc_Config0:PICC_CONFIG; hDevReader:PHandle):Integer;stdcall;external 'SI_ICCReader.dll';//功能:初始化读卡器设备//参数:icc_Config0 -- 读卡器参数指针 ICC_CONFIG指针为NULL,则采用默认参数初始化,ICC_CONFIG具体定义参考结构定义//         hDevReader 返回读卡器操作句柄//返回:=0:正常完成初始化       <>0:初始化出错,调用SIGetErrMessage获取具体的错误信息function  SISelectIFD (hDevReader: THandle; IFDType: Integer):Integer;stdcall;external 'SI_ICCReader.dll';//功能:选择CPU卡(包括社会保障卡/PSAM卡)//参数:hDevReader -- 通过SIReaderInit函数获得的读卡器句柄//      IFDType    -- CPU卡类型,参照标准IC卡类型代码表(0x0c:社保卡槽;0x0d:附卡座PSAM卡槽;0x0E为第一个SAM1卡座,0x0F为第二个SAM2卡座)//返回:     =0:表示操作成功       <>0:表示操作失败,调用SIGetErrMessage获取具体的错误信息function GetReaderStatus(hDevReader: THandle;status: PChar):Integer;stdcall;external 'SI_ICCReader.dll';//功能:获取读卡器状态   给卡片进行上电//参数:hDevReader -- 通过SIReaderInit函数获得的读卡器句柄//         status: '2' 读卡器已连接并已插入社会保障卡//返回:=0:表示操作成功       <>0:表示操作失败,调用SIGetErrMessage获取具体的错误信息function SIReadInfo(hDevReader: THandle;const sDF:PChar; const sEF:PChar; const cRecNo: Byte; sBuffer:PChar):Integer;stdcall;external 'SI_ICCReader.dll';//功能:读取社保卡记录文件信息//参数:hDevReader -- 通过SIReaderInit函数获得的读卡器句柄//         sDF:[IN] :对应目录名称如"DF01","3F00"(MF)。//         sEF:[IN] :对应文件名称如"EF01","EF0C"。//         cRecNo:[IN] :对应文件记录号(不是记录标识),如果为0,则表示读取该文件内所有记录,如果为01-n,则表示读取该文件内某一条记录。//         sBuffer[OUT] :返回读取数据,需要预先分配对应文件内的长度,长度为∑(每个记录字节数) + 1//返回:=0:表示操作成功       <>0:表示操作失败,调用SIGetErrMessage获取具体的错误信息procedure SIGetErrMessage(nErrNo:Integer;sErrMessage:PChar);stdcall;external 'SI_ICCReader.dll';//功能:根据错误代码获取详细错误信息//参数:     NErrNo[IN]:错误代码,见附录错误代码命名方式。//           SErrMessage[OUT]:错误代码所对应的错误信息,已预先分配201个字节长度varForm1: TForm1;implementation{$R *.dfm}procedure TForm1.btnReadICardClick(Sender: TObject);
varnRet:Integer;sBuffer: array[0..200] of Char;sData: array[0..10] of Char;sStatus: array[0..10] of Char;sErrMsg: array[0..50] of Char;icc_Config0:ICC_CONFIG;g_Handle: THandle;
begin//端口信息icc_Config0.port := 100;icc_Config0.baud := 9600;icc_Config0.ICCSlot := 0;icc_Config0.PSAMSlot := 0;icc_Config0.timeout := 0;Memo1.Lines.Clear;nRet := SIReaderInit(@icc_Config0,@g_Handle);if nRet <> 0 thenbegin
//    ZeroMemory(@sErrMsg,SizeOf(sErrMsg));
//    SIGetErrMessage(nRet, sErrMsg);Memo1.Lines.Add('读卡器初始化失败!,错误代码:') ;endelsebeginMemo1.Lines.Add('读卡器初始化成功' );end;//切换卡槽号nRet := SISelectIFD(g_Handle, $0C);if nRet <> 0 thenbeginMemo1.Lines.Add('选择社保卡槽失败!') ;endelsebeginMemo1.Lines.Add('选择社保卡槽成功!');end;// 获取读卡器状态   给卡片进行上电FillChar(sStatus,SizeOf(sStatus),#0);//用0填充sStatusnRet := GetReaderStatus(g_Handle, @sStatus[0]);if (nRet = 0)and(sStatus = '2') thenbegin//附录1:温州市社会保障卡结构
FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffernRet := SIReadInfo(g_Handle, '3F00','EF05', 1, sBuffer);Memo1.Lines.Add('卡的识别码:' + sBuffer);FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffernRet := SIReadInfo(g_Handle, '3F00','EF05',2, sBuffer);Memo1.Lines.Add('卡的类别:' + sBuffer);FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffernRet := SIReadInfo(g_Handle, '3F00','EF05', 3, sBuffer);Memo1.Lines.Add('规范版本:' + sBuffer);FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffernRet := SIReadInfo (g_Handle, '3F00','EF05', 4, sBuffer);Memo1.Lines.Add('初始化机构编号:' + sBuffer);FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffernRet := SIReadInfo(g_Handle, '3F00','EF05', 5, sBuffer);Memo1.Lines.Add('发卡日期:' + sBuffer);FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffernRet := SIReadInfo(g_Handle, '3F00','EF05', 6, sBuffer);Memo1.Lines.Add('卡有效期:' + sBuffer);FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffernRet := SIReadInfo(g_Handle, '3F00','EF05', 7, sBuffer);Memo1.Lines.Add('卡号:' + sBuffer);FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffernRet := SIReadInfo(g_Handle, '3F00','EF06', 1, sBuffer);Memo1.Lines.Add('公民身份证号码:' + sBuffer);FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffernRet := SIReadInfo(g_Handle, '3F00','EF06',2, sBuffer);Memo1.Lines.Add('姓名:' + sBuffer);FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffernRet := SIReadInfo(g_Handle, '3F00','EF06', 3, sBuffer);Memo1.Lines.Add('性别:' + sBuffer);FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffernRet := SIReadInfo (g_Handle, '3F00','EF06', 4, sBuffer);Memo1.Lines.Add('民族:' + sBuffer);FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffernRet := SIReadInfo(g_Handle, '3F00','EF06', 5, sBuffer);Memo1.Lines.Add('出生地:' + sBuffer);FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffernRet := SIReadInfo(g_Handle, '3F00','EF06', 6, sBuffer);Memo1.Lines.Add('出生日期:' + sBuffer);end;end;end.

demo下载

转载于:https://www.cnblogs.com/tc310/p/4166344.html

Delphi调用C++写的dll示例相关推荐

  1. QT调用C#写的Dll

    QT调用C#写的Dll 参见: https://blog.csdn.net/weixin_42420155/article/details/81060945 C#写的dll是没有dllMain入口函数 ...

  2. c++调用c#写的DLL

    c++调用c#写的DLL: 此文章演示了建立c#的dll: c++建立工程,引入dll: 不能解决的问题: 指定dll的路径,在代码里面直接写 #using "xxx.dll" 必 ...

  3. C# 调用C++写的dll的实现方法

    文章目录 **C# 调用C++写的dll的实现方法** 一. dll的编写 2.C#调用 C# 调用C++写的dll的实现方法 C#调用C++的非托管类的dll其实很简单基本就是固定的调用格式. 一. ...

  4. QT调用C++写的Dll

    C#写的dll是没有dllMain入口函数的,是一种中间语言,需要.Net运行时进行做本地化工作,因此如果要调用C#写的dll,需要依赖.Net运行时,然而Qt中还无法直接调用.Net运行时,最好的方 ...

  5. VC调用C#写的DLL

    From: http://hi.baidu.com/ocnc/blog/item/2c7fc45c1d1f1051fbf2c0ea.html VC中调用C#写的DLL时,对C#这边的DLL有要求,即要 ...

  6. 易语言如何调用c dll文件,易语言调用C++写的DLL

    直接调用会弹出堆栈错误的信息,原因是VS默认是__cdcel方式,而易语言是__stdcall,所以调用约定不一致导致堆栈错误. 解决方案很简单,易语言声明DLL函数时"在库中对应命令名&q ...

  7. c#调用C++写的dll导出类,如何实现

    网上看了一些都是调用c++写函数能不能实现c#使用c++写的类各位高手请赐教 解决方案 » 类的有一个成员函数,是返回这个类的指针,那么在C#里面就是一个INTPTR,它是什么你不用管.然后C++文件 ...

  8. QT 调用vs写的dll 使用OutputDebugString输出调试信息

    vs c++写的dll中使用的cout 将调试信息写到控制台中,但qt调用dll时,cout内容没有办法显示了. 解决办法:使用OutputDebugStringA char buf[128];spr ...

  9. 百度语音识别rest html,delphi调用百度语音识别REST API(示例代码)

    delphi调用百度语音识别REST API -20160616 -感谢 魔术猫 和 DelphiTeacher 兄的帮助解决了返回中文乱码的问题! -注:语音的录音格式目前只支持评测8k/16k采样 ...

  10. delphi 调用 c# 写的webservice

    调用helloWorld的返回值是正确的,调用add的时候,传入(1,2)时,返回值却为0,不知什么原因,这个问题困惑了很久,请高手们指教~ 以下是源码 //c#写的webservice的源码 [We ...

最新文章

  1. 看看人家那后端API接口写得,那叫一个巴适~,再看看我的,像坨屎!
  2. 父类指针访问子类成员变量
  3. 给Python初学者的最好练手项目,进来看就对了!
  4. (八)React原理
  5. 前端学习(693):for循环案例之求出偶数奇数之和
  6. C++ 数据抽象 封装 接口
  7. 想了解 spring-cloud-kubernetes,那就先来实战一把官方demo
  8. git add用法详解,参数列表,git add -A/git add -u/git add .区别
  9. 第三季-第5课-Linux编程规范
  10. 为什么交叉熵损失函数可以用作逻辑回归的损失函数?
  11. ImportError: cannot import name 'imresize'
  12. 图解Web服务器网关接口WSGI(Web Server Gateway Interface)
  13. oracle 模糊查询语法
  14. 高三计算机专业vb试题二答案,高三计算机专业VB试题(二).doc
  15. 2022-07-04-5万字长文说清楚到底什么是“车规级”
  16. android emulator ps4,PS4 Simulator模拟器
  17. word2016加载MathType打开时显示“安全警告,宏已被禁用”解决办法
  18. 从0开始搭建深度学习环境-Pytorch-GPU
  19. 搭建网络流量监控cacti
  20. 万年历-java课程设计题_万年历-Java课程设计题(eclipse编辑器)

热门文章

  1. 遍历目录中的所有文件和目录,并生成全路径
  2. RunLoop相关知识
  3. flutter自定义View(CustomPainter) 之 canvas的方法总结
  4. 设计模式-设计原则-迪米特法则
  5. A1089. 阶乘计算
  6. Android判断App是否在前台运行
  7. 【转】LPCTSTR,LPWSTR, PTSTR, LPTSTR区别
  8. 51nod 1130 N的阶乘的长度 V2(斯特林近似)
  9. 算法笔记_045:币值最大化问题(Java)
  10. 大家一起写mvc(二)