Delphi调用C++写的dll示例
最近做一个读市民卡的项目,读卡器公司提供的读市民卡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示例相关推荐
- QT调用C#写的Dll
QT调用C#写的Dll 参见: https://blog.csdn.net/weixin_42420155/article/details/81060945 C#写的dll是没有dllMain入口函数 ...
- c++调用c#写的DLL
c++调用c#写的DLL: 此文章演示了建立c#的dll: c++建立工程,引入dll: 不能解决的问题: 指定dll的路径,在代码里面直接写 #using "xxx.dll" 必 ...
- C# 调用C++写的dll的实现方法
文章目录 **C# 调用C++写的dll的实现方法** 一. dll的编写 2.C#调用 C# 调用C++写的dll的实现方法 C#调用C++的非托管类的dll其实很简单基本就是固定的调用格式. 一. ...
- QT调用C++写的Dll
C#写的dll是没有dllMain入口函数的,是一种中间语言,需要.Net运行时进行做本地化工作,因此如果要调用C#写的dll,需要依赖.Net运行时,然而Qt中还无法直接调用.Net运行时,最好的方 ...
- VC调用C#写的DLL
From: http://hi.baidu.com/ocnc/blog/item/2c7fc45c1d1f1051fbf2c0ea.html VC中调用C#写的DLL时,对C#这边的DLL有要求,即要 ...
- 易语言如何调用c dll文件,易语言调用C++写的DLL
直接调用会弹出堆栈错误的信息,原因是VS默认是__cdcel方式,而易语言是__stdcall,所以调用约定不一致导致堆栈错误. 解决方案很简单,易语言声明DLL函数时"在库中对应命令名&q ...
- c#调用C++写的dll导出类,如何实现
网上看了一些都是调用c++写函数能不能实现c#使用c++写的类各位高手请赐教 解决方案 » 类的有一个成员函数,是返回这个类的指针,那么在C#里面就是一个INTPTR,它是什么你不用管.然后C++文件 ...
- QT 调用vs写的dll 使用OutputDebugString输出调试信息
vs c++写的dll中使用的cout 将调试信息写到控制台中,但qt调用dll时,cout内容没有办法显示了. 解决办法:使用OutputDebugStringA char buf[128];spr ...
- 百度语音识别rest html,delphi调用百度语音识别REST API(示例代码)
delphi调用百度语音识别REST API -20160616 -感谢 魔术猫 和 DelphiTeacher 兄的帮助解决了返回中文乱码的问题! -注:语音的录音格式目前只支持评测8k/16k采样 ...
- delphi 调用 c# 写的webservice
调用helloWorld的返回值是正确的,调用add的时候,传入(1,2)时,返回值却为0,不知什么原因,这个问题困惑了很久,请高手们指教~ 以下是源码 //c#写的webservice的源码 [We ...
最新文章
- 看看人家那后端API接口写得,那叫一个巴适~,再看看我的,像坨屎!
- 父类指针访问子类成员变量
- 给Python初学者的最好练手项目,进来看就对了!
- (八)React原理
- 前端学习(693):for循环案例之求出偶数奇数之和
- C++ 数据抽象 封装 接口
- 想了解 spring-cloud-kubernetes,那就先来实战一把官方demo
- git add用法详解,参数列表,git add -A/git add -u/git add .区别
- 第三季-第5课-Linux编程规范
- 为什么交叉熵损失函数可以用作逻辑回归的损失函数?
- ImportError: cannot import name 'imresize'
- 图解Web服务器网关接口WSGI(Web Server Gateway Interface)
- oracle 模糊查询语法
- 高三计算机专业vb试题二答案,高三计算机专业VB试题(二).doc
- 2022-07-04-5万字长文说清楚到底什么是“车规级”
- android emulator ps4,PS4 Simulator模拟器
- word2016加载MathType打开时显示“安全警告,宏已被禁用”解决办法
- 从0开始搭建深度学习环境-Pytorch-GPU
- 搭建网络流量监控cacti
- 万年历-java课程设计题_万年历-Java课程设计题(eclipse编辑器)