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

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

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

代码:

unit cMain;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, ADODB, StdCtrls, ComCtrls,ActiveX, ExtCtrls; type
TForm1 = class(TForm)
btnReadICard: TButton;
Memo1: TMemo;
procedure btnReadICardClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
//2014-12-11
type
PICC_CONFIG=^ICC_CONFIG;
ICC_CONFIG=record
port: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-11
function 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个字节长度 var
Form1: TForm1; implementation {$R *.dfm} procedure TForm1.btnReadICardClick(Sender: TObject);
var
nRet:Integer;
sBuffer: array[..] of Char;
sData: array[..] of Char;
sStatus: array[..] of Char;
sErrMsg: array[..] of Char;
icc_Config0:ICC_CONFIG;
g_Handle: THandle;
begin
//端口信息
icc_Config0.port := ;
icc_Config0.baud := ;
icc_Config0.ICCSlot := ;
icc_Config0.PSAMSlot := ;
icc_Config0.timeout := ; Memo1.Lines.Clear;
nRet := SIReaderInit(@icc_Config0,@g_Handle);
if nRet <> then
begin
// ZeroMemory(@sErrMsg,SizeOf(sErrMsg));
// SIGetErrMessage(nRet, sErrMsg);
Memo1.Lines.Add('读卡器初始化失败!,错误代码:') ;
end
else
begin
Memo1.Lines.Add('读卡器初始化成功' );
end; //切换卡槽号
nRet := SISelectIFD(g_Handle, $0C);
if nRet <> then
begin
Memo1.Lines.Add('选择社保卡槽失败!') ;
end
else
begin
Memo1.Lines.Add('选择社保卡槽成功!');
end; // 获取读卡器状态 给卡片进行上电
FillChar(sStatus,SizeOf(sStatus),#);//用0填充sStatus
nRet := GetReaderStatus(g_Handle, @sStatus[]);
if (nRet = )and(sStatus = '') then
begin
//附录1:温州市社会保障卡结构 FillChar(sBuffer,SizeOf(sBuffer),#);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF05', , sBuffer);
Memo1.Lines.Add('卡的识别码:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF05',, sBuffer);
Memo1.Lines.Add('卡的类别:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF05', , sBuffer);
Memo1.Lines.Add('规范版本:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#);//用0填充缓冲区sBuffer
nRet := SIReadInfo (g_Handle, '3F00','EF05', , sBuffer);
Memo1.Lines.Add('初始化机构编号:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF05', , sBuffer);
Memo1.Lines.Add('发卡日期:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF05', , sBuffer);
Memo1.Lines.Add('卡有效期:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF05', , sBuffer);
Memo1.Lines.Add('卡号:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF06', , sBuffer);
Memo1.Lines.Add('公民身份证号码:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF06',, sBuffer);
Memo1.Lines.Add('姓名:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF06', , sBuffer);
Memo1.Lines.Add('性别:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#);//用0填充缓冲区sBuffer
nRet := SIReadInfo (g_Handle, '3F00','EF06', , sBuffer);
Memo1.Lines.Add('民族:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF06', , sBuffer);
Memo1.Lines.Add('出生地:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF06', , sBuffer);
Memo1.Lines.Add('出生日期:' + sBuffer); end; end; end.

demo下载

Delphi调用C++写的dll示例的更多相关文章

  1. 发现个delphi调用vc写的Dll中包括pchar參数报错奇怪现象

    发现个delphi调用vc写的Dll中包括pchar參数奇怪现象 procedure中的第一行语句不能直接调用DLL的函数,否则会执行报错,在之前随意加上条语句就不报错了奇怪! vc的DLL源代码地址 ...

  2. Delphi调用c++写的dll (me)

    unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...

  3. Delphi 调用C/C++的Dll(stdcall关键字, 会导致函数名分裂. 此时函数名变成_stdadd@8)

    delphi调用C++写的Dll, 当然这个Dll要求是非MFC的Dll, 这样子才能被delphi调用. 根据C++定义函数的情况, Delphi有不同的相对应的处理方法.1. 声明中不加__std ...

  4. Delphi7程序调用C#写的DLL解决办法(转)

    近来,因工作需要,必须解决Delphi7写的主程序调用C#写的dll的问题.在网上一番搜索,又经过种种试验,最终证明有以下两种方法可行:    编写C#dll的方法都一样,首先在vs2005中创建一个 ...

  5. Delphi7程序调用C#写的DLL解决办法

     近来,因工作需要,必须解决Delphi7写的主程序调用C#写的dll的问题.在网上一番搜索,又经过种种试验,最终证明有以下两种方法可行:    编写C#dll的方法都一样,首先在vs2005中创建一 ...

  6. Delphi 调用C# 编写的DLL方法

    近来,因工作需要,必须解决Delphi写的主程序调用C#写的dll的问题.在网上一番搜索,又经过种种试验,最终证明有以下两种方法可行:    编写C#dll的方法都一样,首先在vs2005中创建一个“ ...

  7. c++ c# java 调用 c++ 写的dll

    1. vs 中新建win32 dll 项目   testdll 添加实现文件       test.cpp #include "stdafx.h" #include <ios ...

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

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

  9. QT调用C#写的Dll

    参见: https://blog.csdn.net/weixin_42420155/article/details/81060945 C#写的dll是没有dllMain入口函数的,是一种中间语言,需要 ...

随机推荐

  1. android 小米手机连接到电脑adb无法识别 解决方案

    下载并安装小米手机助手 它会自动帮你安装驱动程序 安装成功后重启一下adb服务 应该就可以了

  2. STL--自定义类型的排序

    STL的排序太坑了,尤其是在VS2010上重载sort函数的第三个比较参数的时候. invalid operator < 这个错在写多关键字排序的时候就没有停止过. 本来想查书解决,结果各种重载 ...

  3. javaweb学习总结(二十八)——JSTL标签库之核心标签

    一.JSTL标签库介绍 JSTL标签库的使用是为弥补html标签的不足,规范自定义标签的使用而诞生的.使用JSLT标签的目的就是不希望在jsp页面中出现java逻辑代码 二.JSTL标签库的分类 核心 ...

  4. ruby的命名约定

    1 局部变量和方法参数以小写字母开头 2 方法名字以小写字母开头 3 全局变量以$开头 4 实例变量以@开头 5 类变量以@@开头 6 常量以大写字母开头 7  类和模块名以大写字母开头

  5. apache开源项目--Lens

    Lens 提供了一个统一数据分析接口.通过提供一个跨多个数据存储的单一视图来实现数据分析任务切分,同时优化了执行的环境.无缝的集成 Hadoop 实现类似传统数据仓库的功能. 该项目主要特性: 简单元 ...

  6. Apache FileUpload实现文件上传

    今天,我来介绍一个Apache FileUpload这个插件的使用. 首先,到官网下载相关jar包点击这里下载,这里提供是v1.2. 1.在项目中导入相关jar包commons-fileupload- ...

  7. Android获取IMSI和IMEI

    IMSI是一个 唯一的数字, 标识了GSM和UMTS 网络里的唯一一个用户. 它 存储 在手机的SIM卡里,它会通过手机发送到网络上. IMEI也是一串唯一的数字, 标识了 GSM 和 UMTS网络里 ...

  8. MongoDB之三(高级操作 聚合、游标)

    一: 聚合 常见的聚合操作跟sql server一样,有:count,distinct,group,mapReduce. <1> count count是最简单,最容易,也是最常用的聚合工 ...

  9. zookeeper服务器端管理工具

    zookeeper基本是基于API和console进行znode的操作,并没有一个比较方便的操作界面,这里也发现了taobao 伯岩写的一个工具,可以比较方便的查询zookeeper信息. 工具的开发 ...

  10. [King.yue]Ext.NET相比WebForm的优势

    1)更好的用户体验.(生产力++) 虽然WebForm可以使用微软的Ajax以及Ajax控件进行开发,但是用户体验还是远远不及extjs.而且你可以跟客户忽悠,这个功能多么滴难做,多么好,但是我们做出 ...