大家好:我用的是Delphi 7.公司有一考勤机器,厂商提供有考勤机Dll文件.
我需要调用Dll文件中对应的函数读取其中的值.其中Dll文件说明如下:JBC2900E.dll函数说明
注:所有的AR_ID变量代表卡钟地址编号.JBC2900E型地址编号为1-128.
--------------------------------------------------------------------------------
 extern "C" __declspec(dllimport ) __stdcall 
long Open_ComX(char * ComPort,long Baud);
功能:打开串口
参数: ComPort
端口号 如'COM1' `COM2'
Baud       波特率 9600
回车:
0 成功 非0失败
--------------------------------------------------------------------------------
extern "C" __declspec(dllimport ) __stdcall 
long Close_ComX();
功能:关闭串口
回车:
0 成功 非0失败
--------------------------------------------------------------------------------
extern "C" __declspec(dllimport ) __stdcall 
long SearchAR(long AR_ID);
功能:搜索卡钟
回车:0 存在 非0 不存在
--------------------------------------------------------------------------------
extern "C" __declspec(dllimport ) __stdcall 
long SetARAdress(long AR_ID,long Old_AR_ID);
功能:重新设置卡钟地址编号.
参数: AR_ID
新的卡钟地址编号.
Old_AR_ID
      以前的卡钟地址编号.
回车:
0 成功 非0失败
--------------------------------------------------------------------------------
extern "C" __declspec(dllimport ) __stdcall 
long ReadRam2k(long AR_ID,char *DataBuff,long BlockFlag);
功能:读128条数据
参数:
DataBuff
      数据从此参数回车.
BlockFlag
      块标志.
回车:1 数据未完并请求下一块. 0数据完成.
--------------------------------------------------------------------------------
extern "C" __declspec(dllimport ) __stdcall 
long ClearRam(long AR_ID);
功能:清除卡钟数据.
回车:
0 成功 非0失败   
--------------------------------------------------------------------------------
extern "C" __declspec(dllimport) __stdcall 
long GetRecordNumber(long AR_ID,char *RecordNumber,char *LoginNumber);
功能:给出卡钟内的记录数.
参数
   RecordNumber 当前卡钟内的数据记录数.
   LoginNumber  当前卡钟内已注册卡号数.
回车:
0 成功 非0失败
--------------------------------------------------------------------------------还有一些,省略掉了.
--------------------------------------------------------------------------------
我用 Open_ComX函数打开Com1口,SearchAR搜索1号考勤卡机均成功.但用ReadRam2k函数读取其中数据时报错,相关程序代码如下:procedure TForm1.BitBtn1Click(Sender: TObject);
Type TOpen_ComX=Function(Comport:Pchar;Band:Integer):Integer;Stdcall;
//功能:打开串口
Var
Open_ComX:TOpen_ComX;
Handle:THandle;
Comport:Pchar;
Band:Integer;
begin
        Comport:='COM1';//设置Com1口
        Band:=9600;  //设置速率
        Handle:=LoadLibrary('JBC_Attend.dll');
        Open_ComX:=GetProcAddress(Handle,'Open_ComX');
        If Open_ComX(Comport,Band)=0 Then Edit1.Text:='Com1 口开启成功'
        Else Edit1.Text:='Com1 口开启失败';
        FreeLibrary(Handle);
end;procedure TForm1.BitBtn2Click(Sender: TObject);
//功能 搜索考勤 
Type TSearchAR=Function(AD_ID:Integer):Integer;Stdcall;
Var
Search:TSearchar;
Handle:THandle;
AD_ID:Integer;
begin
        AD_ID:=1;
        Handle:=LoadLibrary('JBC_Attend.dll');
        Search:=GetProcAddress(Handle,'SearchAR');
        Edit4.Text:=IntToStr(Search(AD_ID));
        If (Search(AD_ID)=0) Then  Edit2.Text:='搜索考勤 1 号机器成功'
        Else Edit2.Text:='搜索考勤 1 号机器失败';
        FreeLibrary(Handle);
End;procedure TForm1.BitBtn3Click(Sender: TObject);
//读取数据
Type TReadRam2k=Function(AD_ID:Integer;DataBuff:PChar;BlockFlag:Integer):Integer;Stdcall;
Var
ReadRam:TReadRam2k;
Handle:THandle;
AD_ID:Integer;
DataBuff:PChar;
BlockFlag:Integer;
begin
        AD_ID:=1;
        DataBuff:='';
        BlockFlag:=1;
        Handle:=LoadLibrary('JBC_Attend.dll');
        ReadRam:=GetProcAddress(Handle,'ReadRam2k');
        ReadRam(AD_ID,DataBuff,BlockFlag);
        Memo1.Lines.Add(DataBuff);
        FreeLibrary(Handle);
End;
我先将Com1口打开,然后搜索考勤,当我进行资料读取,时报错,如下
Access Violation at Address 00242995 in module JBC_Attend.dll Write of address 00427510
我不明白这是为何!请高手指示!!我如何读取到其中的数据!请提供对应代码!!谢谢
顺便请问我如何给分给回答过问题的人!

解决方案 »

  1.   

    还是静态调用吧!
    ReadRam:=GetProcAddress(Handle,'ReadRam2k');你确信已经找到相应的函数的了吗?
      

  2.   

    我确定已经找到对应的函数并其函数已经工作,否则不会回车如此信息:
    Access Violation at Address 00242995 in module JBC_Attend.dll Write of address 00427510
      

  3.   

    Type TOpen_ComX=Function(Comport:Pchar;Band:Integer):Integer;Stdcall;
    不要放在procedure TForm1.BitBtn2Click(Sender: TObject);下面声明
    放在公共声明的地方, 另外这样改, 另一个函数也一样改.
    procedure TForm1.BitBtn2Click(Sender: TObject);
    //功能 搜索考勤 
    Var
    Search:TSearchar;
    Handle:THandle;
    AD_ID:Integer;
    begin
            AD_ID:=1;
            Handle:=LoadLibrary('JBC_Attend.dll');
            Try
              @Search:=@GetProcAddress(Handle,'SearchAR');
              Edit4.Text:=IntToStr(Search(AD_ID));
              If (Search(AD_ID)=0) Then
                Edit2.Text:='搜索考勤 1 号机器成功'
              Else 
              Edit2.Text:='搜索考勤 1 号机器失败';
           finally
            FreeLibrary(Handle);
           end;
    End;
      

  4.   

    这一句(@Search:=@GetProcAddress(Handle,'SearchAR'))调试通不过;错误报告显示为: Variable required .我不知道加这个是什么意思,请指教!!
      

  5.   

    你也要把Type TSearchAR=Function(AD_ID:Integer):Integer;Stdcall;放在
    类声明的地方;
    (@Search:=@GetProcAddress(Handle,'SearchAR')这里的@作用是确保正确的调用.
      

  6.   

    是哪个位置?以下的A处? B处? C处? D处? E处?请明示!!
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, Buttons;type
      TForm1 = class(TForm)
        Edit1: TEdit;
        A处?
        procedure BitBtn1Click(Sender: TObject);
        procedure BitBtn2Click(Sender: TObject);
        procedure BitBtn3Click(Sender: TObject);
        procedure BitBtn4Click(Sender: TObject);
        procedure BitBtn5Click(Sender: TObject);
        procedure BitBtn6Click(Sender: TObject);
        //Function Search1(AD_ID:Integer):Integer; Stdcall;external 'JBC_Attend.dll'name 'Open_ComX';  private
        { Private declarations }
      public
        B处?
        { Public declarations }
      end;var
      Form1: TForm1;
       C处?
    Implementation
       D处?
    {$R *.dfm}procedure TForm1.BitBtn5Click(Sender: TObject);
    E处?
    Var
    Comport:Pchar;
    Band:Integer;
    Begin
    ..
    End
      

  7.   

    晕头, 你声明一个类放在什么方????????type
      TForm1 = class(TForm)
        Edit1: TEdit;
        A处?
        procedure BitBtn1Click(Sender: TObject);
        procedure BitBtn2Click(Sender: TObject);
        procedure BitBtn3Click(Sender: TObject);
        procedure BitBtn4Click(Sender: TObject);
        procedure BitBtn5Click(Sender: TObject);
        procedure BitBtn6Click(Sender: TObject);
        //Function Search1(AD_ID:Integer):Integer; Stdcall;external 'JBC_Attend.dll'name 'Open_ComX';  private
        { Private declarations }
      public
        { Public declarations }
      end;Type 
      TSearchAR=Function(AD_ID:Integer):Integer;Stdcall;如果不行, 你把那个Dll文件发给我帮你写算了, 给我200分就OK.
      

  8.   

    把Dll及相关的文件传给我, e-mail to :[email protected]
      

  9.   

    我也可以帮你研究一下,发一个给我:[email protected]
    我闲着没事,可能要快些。
      

  10.   

    老兄, 你发给我的JBC2900.txt里面是乱码,我用的XP+SP2简体的, 你是不是繁体的
    你把它转换一下再发一次, 要不就发在网上看.
      

  11.   

    我需要用Delphi读取考勤机的考勤记录.用厂商自带程序读出的数据如下
    0012005091906511200003456018
    0012005091907120900002142018
    我的思路是:1:打开Com1口;2: 考勤机;3: 读取数据
    前两步没问题,后面读取数据有问题.我的相关代码如下
      private
        { Private declarations }
      public    { Public declarations }
      end;var
      Form1: TForm1;
      Type TOpen_ComX=Function(Comport:Pchar;Band:Integer):Integer;Stdcall;
      Type TSearchAR=Function(AD_ID:Integer):Integer;Stdcall;
      Type TReadRam2k=Function(AD_ID:Integer;DataBuff:PChar;BlockFlag:Integer):Integer;Stdcall;
    implementation
    function Open_ComX(Comport:PChar;Band:Integer):Integer; Stdcall external 'JBC_Attend.dll'name 'Open_ComX';
    function Search(AR_ID:Integer):Integer; Stdcall external 'JBC_Attend.dll'name 'SearchAR';{$R *.dfm}
    procedure TForm1.BitBtn1Click(Sender: TObject);//功能:打开串口
    Var
    Open_ComX:TOpen_ComX;
    Handle:THandle;
    Comport:Pchar;
    Band:Integer;
    begin
            Comport:='COM1';//设置Com1口
            Band:=9600;  //设置速率
            Handle:=LoadLibrary('JBC_Attend.dll');
            Open_ComX:=GetProcAddress(Handle,'Open_ComX');
            If Open_ComX(Comport,Band)=0 Then Edit1.Text:='Com1 口开启成功'
            Else Edit1.Text:='Com1 口开启失败';
            FreeLibrary(Handle);
    end;
    procedure TForm1.BitBtn2Click(Sender: TObject);
    //功能: 搜索卡钟
    Var
    Search:TSearchar;
    Handle:THandle;
    AD_ID:Integer;
    begin
            AD_ID:=1;
            Handle:=LoadLibrary('JBC_Attend.dll');
            Try
            Search:=GetProcAddress(Handle,'SearchAR');
            Edit4.Text:=IntToStr(Search(AD_ID));
            If (Search(AD_ID)=0) Then  Edit2.Text:='搜索考勤 1 号机器成功'
            Else Edit2.Text:='搜索考勤 1 号机器失败';
            Finally
            FreeLibrary(Handle);
            End;
    End;procedure TForm1.BitBtn3Click(Sender: TObject);
    //读128条数据
    Var
    ReadRam:TReadRam2k;
    Handle:THandle;
    farfun: TFarProc;
    AD_ID:Integer;
    DataBuff: PChar;
    BlockFlag:Integer;
    begin
            AD_ID:=1;
            BlockFlag:=1;
            Handle:=LoadLibrary('JBC_Attend.dll');
            farfun:=GetProcAddress(Handle,'ReadRam2k');
            If farfun<>nil then
              Begin
                @ReadRam:=farfun;
            ReadRam(AD_ID,DataBuff,BlockFlag);
            Edit3.Text:='记录读取中:'+DataBuff;
            Edit4.Text:='读取状态'+IntToStr(ReadRam(AD_ID,DataBuff,BlockFlag));        Memo1.Lines.Add(DataBuff);
              End;
            FreeLibrary(Handle);
    End;当我执行完前两步再执行读取数据时则报告如下:
    Access Violation at Address 00242995 in module `JBC_Attend.dll ` Write of address 00427510
    请求指教!我如何像厂商那样正常读取数据??请赋源码!!谢谢!!