首页 > 代码库 > Delphi调用C++写的dll示例

Delphi调用C++写的dll示例

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

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

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

 

代码:

unit cMain;interfaceuses  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-11type  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下载

Delphi调用C++写的dll示例