zoukankan      html  css  js  c++  java
  • 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下载

  • 相关阅读:
    今日小结
    Delphi 框架Frames的使用
    Delphi窗体显示后弹出一个对话框的方法
    Structs2学习笔记1
    使用 LaravelExcel 进行 CSV/EXCEL 文件读写
    Mysql函数FIND_IN_SET()的使用方法
    Laravel数据库操作的三种方式
    Laravel5.5 支付宝手机网站支付的教程
    Python之路3【知识点】白话Python编码和文件操作
    艾伟_转载:利用jQuery实现的Ajax 验证用户名是否存在 狼人:
  • 原文地址:https://www.cnblogs.com/tc310/p/4166344.html
Copyright © 2011-2022 走看看