Delphi調用C++寫的dll示例


最近做一個讀市民卡的項目,讀卡器公司提供的讀市民卡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下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM