您的位置:首页 > 编程语言 > Delphi

Delphi调用C++写的dll示例

2014-12-16 09:04 441 查看
最近做一个读市民卡的项目,读卡器公司提供的读市民卡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[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 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 <> 0 then
begin
Memo1.Lines.Add('选择社保卡槽失败!') ;
end
else
begin
Memo1.Lines.Add('选择社保卡槽成功!');
end;

// 获取读卡器状态   给卡片进行上电
FillChar(sStatus,SizeOf(sStatus),#0);//用0填充sStatus
nRet := GetReaderStatus(g_Handle, @sStatus[0]);
if (nRet = 0)and(sStatus = '2') then
begin
//附录1:温州市社会保障卡结构

FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF05', 1, sBuffer);
Memo1.Lines.Add('卡的识别码:' + sBuffer);

FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF05',2, sBuffer);
Memo1.Lines.Add('卡的类别:' + sBuffer);

FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF05', 3, sBuffer);
Memo1.Lines.Add('规范版本:' + sBuffer);

FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer
nRet := SIReadInfo (g_Handle, '3F00','EF05', 4, sBuffer);
Memo1.Lines.Add('初始化机构编号:' + sBuffer);

FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF05', 5, sBuffer);
Memo1.Lines.Add('发卡日期:' + sBuffer);

FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF05', 6, sBuffer);
Memo1.Lines.Add('卡有效期:' + sBuffer);

FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF05', 7, sBuffer);
Memo1.Lines.Add('卡号:' + sBuffer);

FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF06', 1, sBuffer);
Memo1.Lines.Add('公民身份证号码:' + sBuffer);

FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF06',2, sBuffer);
Memo1.Lines.Add('姓名:' + sBuffer);

FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF06', 3, sBuffer);
Memo1.Lines.Add('性别:' + sBuffer);

FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer
nRet := SIReadInfo (g_Handle, '3F00','EF06', 4, sBuffer);
Memo1.Lines.Add('民族:' + sBuffer);

FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF06', 5, sBuffer);
Memo1.Lines.Add('出生地:' + sBuffer);

FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer
nRet := SIReadInfo(g_Handle, '3F00','EF06', 6, sBuffer);
Memo1.Lines.Add('出生日期:' + sBuffer);

end;

end;

end.


demo下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: