DLL主要功能是用来读指定型号的IC卡,总共有六七个对外提供的函数,但其中有一个参数最多,也是最重要的函数怎么试也不行,就是无法将所有参数信息都正确的读出来,请大家多提点建议,到底应该怎么办呢?十万火急,救命哪。
关于DLL函数的声明文档如下:(就是这个函数,一旦正确读到卡内信息,它就会抛出一个异常,并且TRY不住,读到的值也只有部分正确。好几天了,试了无数种办法,怎么都不行,快崩溃了。)
Siic32.dll接口函数说明
iReadBasicInfo
String : pchar
long  iReadBasicInfo(HANDLE hCom, char* Pin, char* CardCode, 
char* SiCode, char* Name, char* Sex, char* Nation, char* Personid,
char* UnitCode, char* UnitName, char* Address, char* PostCode,
char* Tel, char* PersonType, char* Issueid, char* ExpireDate,
char* ErrMsg)

输入参数:
参数 涵义 数据类型 长度
Hcom HANDLE
Pin 字符串 6输出参数:
参数 涵义 数据类型 长度
CardCode 字符串 9
SiCode 字符串 18
Name 字符串 30
Sex 字符串 1
Nation 字符串 2
Personid 字符串 18
UnitCode 字符串 9
UnitName 字符串 70
Address 字符串 80
PostCode 字符串 6
Tel 字符串 15
PersonType 字符串 2
Issueid 字符串 24
ExpireDate 字符串 8
ErrMsg 字符串 返回值:
返回值类型:整数
返回值 涵义
0 处理成功
其它 处理失败我在DELPHI中是这样做的:unit Unit1;interfaceuses
  ShareMem, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;type
  TForm1 = class(TForm)
    Label1: TLabel;
    Edit1: TEdit;
    Label2: TLabel;
    Edit2: TEdit;
    Button1: TButton;
    Label3: TLabel;
    Edit3: TEdit;
    Label4: TLabel;
    Edit4: TEdit;
    Label5: TLabel;
    Edit5: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;var
  Form1: TForm1;implementationuses CommUnit2;{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
Var
  li_com : Pointer;
  li_rtn:Integer;
  ls_rtn:String;
  ls_card:PAnsiChar;
  ls_CardCode :PChar;
  ls_SiCode:PChar;
  ls_Name:PChar;
  ls_Sex:PChar;
  ls_Nation:PChar;
  ls_Personid:PChar;
  ls_UnitCode:PChar;
  ls_UnitName:PChar;
  ls_Address:PChar;
  ls_PostCode:PChar;
  ls_Tel:PChar;
  ls_PersonType:PChar;
  ls_Issueid:PChar;
  ls_ExpireDate:PChar;
  ls_ErrMsg:PChar;
begin
  ls_rtn := '';
  li_com := MyCom_Open(1,ls_rtn);
  Edit1.Text := '1';
  If li_com = pinteger(0) THen
  Begin
    ShowMessage(ls_rtn);
    Exit;
  End;
  ShowMessage('open ok');
  ls_rtn := '';
  li_rtn := MyCom_Test(li_com,ls_rtn);
  if li_rtn <> 0 then
  Begin
    ShowMessage(ls_rtn);
    MyCom_Close(li_com,ls_rtn);
    Exit;
  end;
  ShowMessage('test ok '+ls_rtn);
  ls_rtn := '';
  li_rtn := Myicc_testcard(li_com,ls_rtn);
  If li_rtn<>0 Then
  Begin
    ShowMessage('请插入IC卡!'+ls_rtn);
    MyCom_Close(li_com,ls_rtn);
    Exit;
  end;
  ShowMessage('testcard ok '+ls_rtn);
  ls_rtn := '';
  ls_card := '';
  li_rtn := MyiGetCardCode(li_com,ls_rtn);
  if li_rtn <> 0 then
  begin
    Application.MessageBox(pchar(ls_rtn),'错误消息',MB_OK+MB_ICONERROR);
    exit;
  end;
  Edit3.Text := ls_rtn;
  ShowMessage('cardcode ok '+ls_rtn);
  if MY_iReadBasicInfo(li_com,PChar(Edit2.Text),ls_CardCode,ls_SiCode,ls_Name,
    ls_Sex,ls_Nation,ls_Personid,ls_UnitCode,ls_UnitName,
    ls_Address,ls_PostCode,ls_Tel,ls_PersonType,ls_Issueid,
    ls_ExpireDate,ls_ErrMsg,ls_rtn) <> 0 then
  begin
    Application.MessageBox(pchar(ls_rtn),'错误消息',MB_OK+MB_ICONERROR);
  end
  else
  begin   //  FillChar(@ls_CardCode,9,0);
//    FillChar(@ls_SiCode,18,0);
  //  FillChar(@ls_Name,30,0);
 //   FillChar(@ls_Sex,1,0);
 ////  FillChar(@ls_Nation,2,0);
  //  FillChar(@ls_Personid,18,0);
  //  FillChar(@ls_UnitCode,9,0);
  //  FillChar(@ls_UnitName,70,0);
  //  FillChar(@ls_Address,80,0);
  //  FillChar(@ls_PostCode,6,0);
   // FillChar(@ls_Tel,15,0);
   // FillChar(@ls_PersonType,2,0);
  //  FillChar(@ls_Issueid,24,0);
 //   FillChar(@ls_ExpireDate,8,0);
 {    ShowMessage('ok');
     Memo1.Lines.Add(pchar(@ls_cardCode));
     Memo1.Lines.Add(pchar(@ls_SiCode));
     Memo1.Lines.Add(pchar(@ls_Name));
     Memo1.Lines.Add(pchar(@ls_Sex));
     Memo1.Lines.Add(pchar(@ls_Nation));
     Memo1.Lines.Add(pchar(@ls_Personid));
     Memo1.Lines.Add(pchar(@ls_UnitCode));
     Memo1.Lines.Add(pchar(@ls_UnitName));
     Memo1.Lines.Add(pchar(@ls_Address));
     Memo1.Lines.Add(pchar(@ls_PostCode));
     Memo1.Lines.Add(pchar(@ls_Tel));
     Memo1.Lines.Add(pchar(@ls_PersonType));
     Memo1.Lines.Add(pchar(@ls_Issueid));
     Memo1.Lines.Add(pchar(@ls_ExpireDate));}    Edit3.Text := pchar(@ls_CardCode);
    Edit4.Text := pchar(@ls_SiCode);
    Edit5.Text := pchar(@ls_Name);
    ShowMessage('readbasicinfo ok');
    ls_rtn := '';
    Mycpu_power_off(li_com,ls_rtn);
    ShowMessage('power_off ok '+ls_rtn);
    ls_rtn := '';
    MyCom_Close(li_com,ls_rtn);
    ShowMessage('close ok ' +ls_rtn);  end;
end;end.

解决方案 »

  1.   

    unit CommUnit2;
    interface
    uses
      ShareMem,SysUtils,Windows,StrUtils,Classes,db,adodb,forms;
    Function MyCom_Open(icdev: Integer; var ls_rtn :String):Pointer;
    procedure MyCom_Close(hcom: Pointer; var ls_rtn :String);
    Function MyCom_Test(hcom: Pointer; var ls_rtn :String) :integer;
    Function Myicc_testcard(hcom: Pointer; var ls_rtn :String) :integer;
    Function Mycpu_power_off(hcom: Pointer; var ls_rtn :String) :integer;
    Function MY_iReadBasicInfo(hCom: Pointer; Pin: Pchar; out CardCode: Pchar; out SiCode : 
    Pchar;  out Name: Pchar;out Sex: Pchar; out Nation: Pchar;  out Personid: Pchar; out UnitCode: Pchar; out UnitName: Pchar;out Address: Pchar; out PostCode: Pchar; out Tel: Pchar;  out PersonType: Pchar; out Issueid: Pchar;
    out ExpireDate: Pchar;  out ErrMsg: Pchar; var ls_rtn :String): Integer;
    Function MyiGetCardCode(hcom: Pointer; var ls_rtn :String) :integer;
    Var
      gs_COM_PORT:String;
    implementation
    Function iGetCardCode(hCom: Pointer;out CardCode:PChar;out ErrMsg:PChar):Integer;stdcall; 
    external 'Siic32.dll';Function iReadBasicInfo(hcom: Pointer; Pin: PChar; out CardCode: Pchar; out SiCode : Pchar;  
    out Name: Pchar;out Sex: Pchar; out Nation: Pchar;  out Personid: Pchar; out UnitCode: Pchar; out UnitName: Pchar;out Address: Pchar; out PostCode: Pchar; out Tel: Pchar;  out PersonType: Pchar; out Issueid: Pchar;out ExpireDate: Pchar;  out ErrMsg: Pchar):integer; stdcall; external 'Siic32.dll' name 'iReadBasicInfo';Function MyCom_open(icdev: Integer; var ls_rtn :String):Pointer;
    Type
      TCom_open = Function(icdev: Integer):Pointer;stdcall;
    Var
      Com_open:TCom_open;
      h: THandle;
      com_flag : Pointer;
    Begin
      Result := 0;
      com_flag := 0;
      ls_rtn := '';
      
      h := LoadLibrary( 'Hnic32.dll' );
      If h = 0 Then
      Begin
        ls_rtn := '装入DLL文件(Hnic32)失败!';
        Exit;
      End;  Try
        @Com_open := GetProcAddress(h, PChar('com_open'));
        
        If @Com_open <> Nil Then
          com_flag := Com_open(icdev)
        Else
          ls_rtn := '装入方法(' + 'com_open' + ')失败!';
      Finally
        FreeLibrary(h);
      End;  if com_flag = pinteger(0) then
         ls_rtn := '打开读卡器通讯端口COM'+inttostr(icdev)+'失败!'
      else
         Result := com_flag;
    end;//关闭新乡医保读卡器通信端口
    procedure MyCom_Close(hcom: Pointer; var ls_rtn :String);
    Type
      TCom_close = procedure(hcom: Pointer);stdcall;
    Var
      Com_close:TCom_close;
      h: THandle;
    Begin
      ls_rtn := '';  h := LoadLibrary('Hnic32.dll' );
      If h = 0 Then
      Begin
        ls_rtn := '装入DLL文件(Hnic32)失败!';
        Exit;
      End;
      Try
        @Com_close := GetProcAddress(h, PChar('com_close'));
        
        If @Com_close <> Nil Then
          Com_close(hcom)
        Else
          ls_rtn := '装入方法(' + 'Com_close' + ')失败!';
      except
      on E: Exception do
        begin
          ls_rtn := '半闭读卡器通讯端口COM'+gs_COM_PORT+'失败!'+^M+^J+E.Message;
        end;
      End;
      FreeLibrary(h);
    end;
    //检测读写器与通讯端口是否联结
    Function MyCom_Test(hcom: Pointer; var ls_rtn :String) :integer;
    Type
      TCom_Test = Function(hcom: Pointer):integer;stdcall;
    Var
      Com_Test:TCom_Test;
      h: THandle;
      com_flag :integer;
    Begin
      Result := 1;
      com_flag := 1;
      ls_rtn := '';
      
      h := LoadLibrary('Hnic32.dll' );
      If h = 0 Then
      Begin
        ls_rtn := '装入DLL文件(Hnic32)失败!';
        Exit;
      End;  Try
        @Com_Test := GetProcAddress(h, PChar('com_test'));
        
        If @Com_Test <> Nil Then
          com_flag := Com_Test(hcom)
        Else
          ls_rtn := '装入方法(' + 'Com_Test' + ')失败!';
      Finally
        FreeLibrary(h);
      End;  if com_flag = 1 then
      begin
        if ls_rtn = '' then
          ls_rtn := '读卡器与通讯端口COM'+gs_COM_PORT+'未正常建立联结!';
      end
      else
         Result := com_flag;
    end;//查询读写器中当前卡座的卡片状态
    Function Myicc_testcard(hcom: Pointer; var ls_rtn :String) :integer;
    Type
      Ticc_testcard = Function(hcom: Pointer):integer;stdcall;
    Var
      icc_testcard: Ticc_testcard;
      h: THandle;
    Begin
      Result := -1;
      ls_rtn := '';
      
      h := LoadLibrary('Hnic32.dll' );
      If h = 0 Then
      Begin
        ls_rtn := '装入DLL文件(Hnic32)失败!';
        Exit;
      End;  Try
        @icc_testcard := GetProcAddress(h, PChar('icc_testcard'));
        
        If @icc_testcard <> Nil Then
          Result := icc_testcard(hcom)
        Else
          ls_rtn := '装入方法(' + 'icc_testcard' + ')失败!';
      except
      on E: Exception do
        begin
          Result := -2;
          ls_rtn := '查询读卡器中当前卡座的卡片状态失败!'+^M+^J+E.Message;
        end;
      End;
      FreeLibrary(h);
    end;//给IC卡下电
    Function Mycpu_power_off(hcom: Pointer; var ls_rtn :String) :integer;
    Type
      Tcpu_power_off = Function(hcom: Pointer):integer;stdcall;
    Var
      cpu_power_off: Tcpu_power_off;
      h: THandle;
    Begin
      Result := -1;
      ls_rtn := '';
      
      h := LoadLibrary('Hnic32.dll' );
      If h = 0 Then
      Begin
        ls_rtn := '装入DLL文件(Hnic32)失败!';
        Exit;
      End;
      Try
        @cpu_power_off := GetProcAddress(h, PChar('cpu_power_off'));
        
        If @cpu_power_off <> Nil Then
          Result := cpu_power_off(hcom)
        Else
          ls_rtn := '装入方法(' + 'icc_testcard' + ')失败!';
      except
      on E: Exception do
        begin
          Result := -1;
          ls_rtn := '给IC卡下电失败!'+^M+^J+E.Message;
        end;
      End;
      FreeLibrary(h);
    end;//读卡基本信息
    Function MY_iReadBasicInfo(hCom: Pointer; Pin: Pchar; out CardCode: Pchar; out SiCode : 
    Pchar;  out Name: Pchar;out Sex: Pchar; out Nation: Pchar;  out Personid: Pchar; out UnitCode: Pchar; out UnitName: Pchar;out Address: Pchar; out PostCode: Pchar; out Tel: Pchar;  out PersonType: Pchar; out Issueid: Pchar;out ExpireDate: Pchar;  out ErrMsg: Pchar; var ls_rtn :String): Integer;
    Type
      TiReadBasicInfo = Function(hcom: Pointer; Pin: Pchar; out CardCode: Pchar; out SiCode : 
    Pchar;  out Name: Pchar;out Sex: Pchar; out Nation: Pchar;  out Personid: Pchar; out UnitCode: Pchar; out UnitName: Pchar;out Address: Pchar; out PostCode: Pchar; out Tel: Pchar;  out PersonType: Pchar; outIssueid: Pchar;out ExpireDate: Pchar;  out ErrMsg: Pchar):integer; stdcall;
    Var
      tReadBasicInfo: TiReadBasicInfo;
      h: THandle;
    Begin
      Result := -1;
      ls_rtn := '';
      h := LoadLibrary('Siic32.dll' );
      If h = 0 Then
      Begin
        ls_rtn := '装入DLL文件(Siic32)失败!';
        Exit;
      End;
      Try
        @tReadBasicInfo := GetProcAddress(h, PChar('iReadBasicInfo'));    If @iReadBasicInfo <> Nil Then
        begin
          Result := tReadBasicInfo(hCom,Pin,CardCode,SiCode,Name,Sex,Nation,Personid,UnitCode,UnitName,Address,PostCode,Tel,
          PersonType,Issueid,ExpireDate,ErrMsg);
           //以上为动态调用读卡信息的方法
    //此注释部分为静态调用代码
       {    if iReadBasicInfo(hCom,Pin,
                              CardCode,
                              SiCode,
                              Name,
                              Sex,
                              Nation,
                              Personid,
                              UnitCode,
                              UnitName,
                              Address,
                              PostCode,
                              Tel,
                              PersonType,
                              Issueid,
                              ExpireDate,
                              ErrMsg
                              )   <> 0 then
           begin
             ls_rtn := pchar(@ErrMsg);
             if trim(ls_rtn) = '' then
             ls_rtn := '调用(Siic32.dll)中的iReadBasicInfo函数出现异常!';
           end
           else
             Result := 0;  }
        end
        Else
          ls_rtn := '装入方法(' + 'iReadBasicInfo' + ')失败!';
      except
      on E: Exception do
        begin
          Result := -1;
          ls_rtn := '读IC卡基本信息出现异常!'+^M+^J+E.Message;
        end;
      End;
      if Result = -2 then
         ls_rtn := '密码不在规定的输入范围之内!'
      else
      if Result <> 0 then
         ls_rtn := pchar(@ErrMsg);
      Application.MessageBox(pchar(inttostr(Result)),'返回值',MB_OK);
      FreeLibrary(h);
    end;
    end.
    这是我写的测试程序的第二个函数单元。
      

  2.   

    interface部分的DLL函数加上stdcall关键字,implementation部分的DLL函数的stdcall关键字可以不要
      

  3.   

    interface部分的DLL函数加上stdcall关键字,去掉函数参数的out关键字,因为PChar本身就是指针,加上out后就相当于c的char **而不是char *了
      

  4.   

    楼主,这样的问题我早就遇到了,而且也是读卡器的读写函数,这个是由于Pascl与C的参数调用顺序不一致引起的,最好用VC进行封装一个DLL后,再进行调用,绝对没问题了。
      

  5.   

    在调用iReadBasicInfo之前必须给指针参数分配内存,比如:ls_CardCode:=AllocMem(9);不要认为这些工作iReadBasicInfo会给你做。