大家好:我用的是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.   

    不好意思!标题写错了!改为
    如何用Delphi读取dll文件中函数传回的值!!
      

  2.   

    DataBuff:array[0..256] of char;试试呢?
      

  3.   

    楼主:
    把delphi中的函数定义后的stdcall换成cdecl就可以了。
    有问题和我联系。[email protected]
      

  4.   


      具体情况不是很清楚,但我想是不是应该在程序一开始时就用 Loadlibrar()加载动态库,
    而在整个程序关闭时,在用FreeLibrary()去释放动态库.可以试一下
      

  5.   

    DataBuff需要分配给它存储空间, ReadRam函数不会自动给它分配的。DataBuff := PChar(StringOfChar(' ', 1024));
      

  6.   


    extern "C" __declspec(dllimport ) __stdcall
    long ReadRam2k(long AR_ID,char *DataBuff,long BlockFlag);
    为例Delphi 中声明为
    function ReadRam2k(AR_ID: Longint, DataBuff: PChar; BlockFlag: Longint): Longint; stdcall; external 'JBC2900E.dll';调用例子:
    var
    arrBuff: array[0..1024] of Char;
    intSize: Integer;
    begin
    // FAR_ID 为卡钟 ID
    intSize := ReadRam2k(FAR_ID, arrBuff, 1024);
    arrBuff[intSize] := #0;// arrBuff 就是读到的数据
    // ??? ... ...
    end;动态库最好使用静态加载, 你的程序中每次调用一个函数就加载和释放动态库, 所以肯定会出问题, 因为重新加载时, 数据已经重新初始化了.