如何用Delphi读取dll文件中函数返回的值!! ( 积分: 100 )

  • 主题发起人 主题发起人 sosmao
  • 开始时间 开始时间
S

sosmao

Unregistered / Unconfirmed
GUEST, unregistred user!
大家好:我用的是Delphi 7.公司有一考勤机器,厂商提供有考勤机Dll文件.<br>我需要调用Dll文件中对应的函数读取其中的值.其中Dll文件说明如下:JBC2900E.dll函数说明<br><br>注:所有的AR_ID变量代表卡钟地址编号.JBC2900E型地址编号为1-128.<br>--------------------------------------------------------------------------------<br> extern &quot;C&quot; __declspec(dllimport ) __stdcall <br>long Open_ComX(char * ComPort,long Baud);<br>功能:打开串口<br>参数: ComPort<br>端口号 如'COM1' `COM2'<br>Baud &nbsp; &nbsp; &nbsp; 波特率 9600<br>回车:<br>0 成功 非0失败<br>--------------------------------------------------------------------------------<br>extern &quot;C&quot; __declspec(dllimport ) __stdcall <br>long Close_ComX();<br>功能:关闭串口<br>回车:<br>0 成功 非0失败<br>--------------------------------------------------------------------------------<br>extern &quot;C&quot; __declspec(dllimport ) __stdcall <br>long SearchAR(long AR_ID);<br>功能:搜索卡钟<br>回车: 0 存在 非0 不存在<br>--------------------------------------------------------------------------------<br>extern &quot;C&quot; __declspec(dllimport ) __stdcall <br>long ReadRam2k(long AR_ID,char *DataBuff,long BlockFlag);<br>功能:读128条数据<br>参数:<br>DataBuff<br> &nbsp; &nbsp; &nbsp;数据从此参数返回.<br>BlockFlag<br> &nbsp; &nbsp; &nbsp;块标志.<br>返回:1 数据未完并请求下一块. 0数据完成.<br>我需要用Delphi读取考勤机的考勤记录.用厂商自带程序读出的数据如下<br>0012005091906511200003456018<br>0012005091907120900002142018<br>我的思路是:1:打开Com1口;2: 考勤机;3: 读取数据<br>前两步没问题,后面读取数据有问题.我的相关代码如下<br> &nbsp;private<br> &nbsp; &nbsp;{ Private declarations }<br> &nbsp;public<br><br> &nbsp; &nbsp;{ Public declarations }<br> &nbsp;end;<br><br>var<br> &nbsp;Form1: TForm1;<br> &nbsp;Type TOpen_ComX=Function(Comport:Pchar;Band:Integer):Integer;Stdcall;<br> &nbsp;Type TSearchAR=Function(AD_ID:Integer):Integer;Stdcall;<br> &nbsp;Type TReadRam2k=Function(AD_ID:Integer;DataBuff:PChar;BlockFlag:Integer):Integer;Stdcall;<br>implementation<br>function Open_ComX(Comport:PChar;Band:Integer):Integer; Stdcall external 'JBC_Attend.dll'name 'Open_ComX';<br>function Search(AR_ID:Integer):Integer; Stdcall external 'JBC_Attend.dll'name 'SearchAR';<br><br><br><br>{$R *.dfm}<br>procedure TForm1.BitBtn1Click(Sender: TObject);<br><br>//功能:打开串口<br>Var<br>Open_ComX:TOpen_ComX;<br>Handle:THandle;<br>Comport:Pchar;<br>Band:Integer;<br>begin<br> &nbsp; &nbsp; &nbsp; &nbsp;Comport:='COM1';//设置Com1口<br> &nbsp; &nbsp; &nbsp; &nbsp;Band:=9600; &nbsp;//设置速率<br> &nbsp; &nbsp; &nbsp; &nbsp;Handle:=LoadLibrary('JBC_Attend.dll');<br> &nbsp; &nbsp; &nbsp; &nbsp;Open_ComX:=GetProcAddress(Handle,'Open_ComX');<br> &nbsp; &nbsp; &nbsp; &nbsp;If Open_ComX(Comport,Band)=0 Then Edit1.Text:='Com1 口开启成功'<br> &nbsp; &nbsp; &nbsp; &nbsp;Else Edit1.Text:='Com1 口开启失败';<br> &nbsp; &nbsp; &nbsp; &nbsp;FreeLibrary(Handle);<br>end;<br><br><br>procedure TForm1.BitBtn2Click(Sender: TObject);<br>//功能: 搜索卡钟<br>Var<br>Search:TSearchar;<br>Handle:THandle;<br>AD_ID:Integer;<br>begin<br> &nbsp; &nbsp; &nbsp; &nbsp;AD_ID:=1;<br> &nbsp; &nbsp; &nbsp; &nbsp;Handle:=LoadLibrary('JBC_Attend.dll');<br> &nbsp; &nbsp; &nbsp; &nbsp;Try<br> &nbsp; &nbsp; &nbsp; &nbsp;Search:=GetProcAddress(Handle,'SearchAR');<br> &nbsp; &nbsp; &nbsp; &nbsp;Edit4.Text:=IntToStr(Search(AD_ID));<br> &nbsp; &nbsp; &nbsp; &nbsp;If (Search(AD_ID)=0) Then &nbsp;Edit2.Text:='搜索考勤 1 号机器成功'<br> &nbsp; &nbsp; &nbsp; &nbsp;Else Edit2.Text:='搜索考勤 1 号机器失败';<br> &nbsp; &nbsp; &nbsp; &nbsp;Finally<br> &nbsp; &nbsp; &nbsp; &nbsp;FreeLibrary(Handle);<br> &nbsp; &nbsp; &nbsp; &nbsp;End;<br>End;<br><br>procedure TForm1.BitBtn3Click(Sender: TObject);<br>//读128条数据<br>Var<br>ReadRam:TReadRam2k;<br>Handle:THandle;<br>farfun: TFarProc;<br>AD_ID:Integer;<br>DataBuff: PChar;<br>BlockFlag:Integer;<br>begin<br> &nbsp; &nbsp; &nbsp; &nbsp;AD_ID:=1;<br> &nbsp; &nbsp; &nbsp; &nbsp;BlockFlag:=1;<br> &nbsp; &nbsp; &nbsp; &nbsp;Handle:=LoadLibrary('JBC_Attend.dll');<br> &nbsp; &nbsp; &nbsp; &nbsp;farfun:=GetProcAddress(Handle,'ReadRam2k');<br> &nbsp; &nbsp; &nbsp; &nbsp;If farfun&lt;&gt;nil then<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Begin<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@ReadRam:=farfun;<br> &nbsp; &nbsp; &nbsp; &nbsp;ReadRam(AD_ID,DataBuff,BlockFlag);<br> &nbsp; &nbsp; &nbsp; &nbsp;Edit3.Text:='记录读取中:'+DataBuff;<br> &nbsp; &nbsp; &nbsp; &nbsp;Edit4.Text:='读取状态'+IntToStr(ReadRam(AD_ID,DataBuff,BlockFlag));<br><br> &nbsp; &nbsp; &nbsp; &nbsp;Memo1.Lines.Add(DataBuff);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;End;<br> &nbsp; &nbsp; &nbsp; &nbsp;FreeLibrary(Handle);<br>End;<br><br>当我执行完前两步再执行读取数据时则报告如下:<br>Access Violation at Address 00242995 in module `JBC_Attend.dll ` Write of address 00427510<br>请求指教!我如何像厂商那样正常读取数据??请赋源码!!谢谢!!
 
大家好:我用的是Delphi 7.公司有一考勤机器,厂商提供有考勤机Dll文件.<br>我需要调用Dll文件中对应的函数读取其中的值.其中Dll文件说明如下:JBC2900E.dll函数说明<br><br>注:所有的AR_ID变量代表卡钟地址编号.JBC2900E型地址编号为1-128.<br>--------------------------------------------------------------------------------<br> extern &quot;C&quot; __declspec(dllimport ) __stdcall <br>long Open_ComX(char * ComPort,long Baud);<br>功能:打开串口<br>参数: ComPort<br>端口号 如'COM1' `COM2'<br>Baud &nbsp; &nbsp; &nbsp; 波特率 9600<br>回车:<br>0 成功 非0失败<br>--------------------------------------------------------------------------------<br>extern &quot;C&quot; __declspec(dllimport ) __stdcall <br>long Close_ComX();<br>功能:关闭串口<br>回车:<br>0 成功 非0失败<br>--------------------------------------------------------------------------------<br>extern &quot;C&quot; __declspec(dllimport ) __stdcall <br>long SearchAR(long AR_ID);<br>功能:搜索卡钟<br>回车: 0 存在 非0 不存在<br>--------------------------------------------------------------------------------<br>extern &quot;C&quot; __declspec(dllimport ) __stdcall <br>long ReadRam2k(long AR_ID,char *DataBuff,long BlockFlag);<br>功能:读128条数据<br>参数:<br>DataBuff<br> &nbsp; &nbsp; &nbsp;数据从此参数返回.<br>BlockFlag<br> &nbsp; &nbsp; &nbsp;块标志.<br>返回:1 数据未完并请求下一块. 0数据完成.<br>我需要用Delphi读取考勤机的考勤记录.用厂商自带程序读出的数据如下<br>0012005091906511200003456018<br>0012005091907120900002142018<br>我的思路是:1:打开Com1口;2: 考勤机;3: 读取数据<br>前两步没问题,后面读取数据有问题.我的相关代码如下<br> &nbsp;private<br> &nbsp; &nbsp;{ Private declarations }<br> &nbsp;public<br><br> &nbsp; &nbsp;{ Public declarations }<br> &nbsp;end;<br><br>var<br> &nbsp;Form1: TForm1;<br> &nbsp;Type TOpen_ComX=Function(Comport:Pchar;Band:Integer):Integer;Stdcall;<br> &nbsp;Type TSearchAR=Function(AD_ID:Integer):Integer;Stdcall;<br> &nbsp;Type TReadRam2k=Function(AD_ID:Integer;DataBuff:PChar;BlockFlag:Integer):Integer;Stdcall;<br>implementation<br>function Open_ComX(Comport:PChar;Band:Integer):Integer; Stdcall external 'JBC_Attend.dll'name 'Open_ComX';<br>function Search(AR_ID:Integer):Integer; Stdcall external 'JBC_Attend.dll'name 'SearchAR';<br><br><br><br>{$R *.dfm}<br>procedure TForm1.BitBtn1Click(Sender: TObject);<br><br>//功能:打开串口<br>Var<br>Open_ComX:TOpen_ComX;<br>Handle:THandle;<br>Comport:Pchar;<br>Band:Integer;<br>begin<br> &nbsp; &nbsp; &nbsp; &nbsp;Comport:='COM1';//设置Com1口<br> &nbsp; &nbsp; &nbsp; &nbsp;Band:=9600; &nbsp;//设置速率<br> &nbsp; &nbsp; &nbsp; &nbsp;Handle:=LoadLibrary('JBC_Attend.dll');<br> &nbsp; &nbsp; &nbsp; &nbsp;Open_ComX:=GetProcAddress(Handle,'Open_ComX');<br> &nbsp; &nbsp; &nbsp; &nbsp;If Open_ComX(Comport,Band)=0 Then Edit1.Text:='Com1 口开启成功'<br> &nbsp; &nbsp; &nbsp; &nbsp;Else Edit1.Text:='Com1 口开启失败';<br> &nbsp; &nbsp; &nbsp; &nbsp;FreeLibrary(Handle);<br>end;<br><br><br>procedure TForm1.BitBtn2Click(Sender: TObject);<br>//功能: 搜索卡钟<br>Var<br>Search:TSearchar;<br>Handle:THandle;<br>AD_ID:Integer;<br>begin<br> &nbsp; &nbsp; &nbsp; &nbsp;AD_ID:=1;<br> &nbsp; &nbsp; &nbsp; &nbsp;Handle:=LoadLibrary('JBC_Attend.dll');<br> &nbsp; &nbsp; &nbsp; &nbsp;Try<br> &nbsp; &nbsp; &nbsp; &nbsp;Search:=GetProcAddress(Handle,'SearchAR');<br> &nbsp; &nbsp; &nbsp; &nbsp;Edit4.Text:=IntToStr(Search(AD_ID));<br> &nbsp; &nbsp; &nbsp; &nbsp;If (Search(AD_ID)=0) Then &nbsp;Edit2.Text:='搜索考勤 1 号机器成功'<br> &nbsp; &nbsp; &nbsp; &nbsp;Else Edit2.Text:='搜索考勤 1 号机器失败';<br> &nbsp; &nbsp; &nbsp; &nbsp;Finally<br> &nbsp; &nbsp; &nbsp; &nbsp;FreeLibrary(Handle);<br> &nbsp; &nbsp; &nbsp; &nbsp;End;<br>End;<br><br>procedure TForm1.BitBtn3Click(Sender: TObject);<br>//读128条数据<br>Var<br>ReadRam:TReadRam2k;<br>Handle:THandle;<br>farfun: TFarProc;<br>AD_ID:Integer;<br>DataBuff: PChar;<br>BlockFlag:Integer;<br>begin<br> &nbsp; &nbsp; &nbsp; &nbsp;AD_ID:=1;<br> &nbsp; &nbsp; &nbsp; &nbsp;BlockFlag:=1;<br> &nbsp; &nbsp; &nbsp; &nbsp;Handle:=LoadLibrary('JBC_Attend.dll');<br> &nbsp; &nbsp; &nbsp; &nbsp;farfun:=GetProcAddress(Handle,'ReadRam2k');<br> &nbsp; &nbsp; &nbsp; &nbsp;If farfun&lt;&gt;nil then<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Begin<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@ReadRam:=farfun;<br> &nbsp; &nbsp; &nbsp; &nbsp;ReadRam(AD_ID,DataBuff,BlockFlag);<br> &nbsp; &nbsp; &nbsp; &nbsp;Edit3.Text:='记录读取中:'+DataBuff;<br> &nbsp; &nbsp; &nbsp; &nbsp;Edit4.Text:='读取状态'+IntToStr(ReadRam(AD_ID,DataBuff,BlockFlag));<br><br> &nbsp; &nbsp; &nbsp; &nbsp;Memo1.Lines.Add(DataBuff);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;End;<br> &nbsp; &nbsp; &nbsp; &nbsp;FreeLibrary(Handle);<br>End;<br><br>当我执行完前两步再执行读取数据时则报告如下:<br>Access Violation at Address 00242995 in module `JBC_Attend.dll ` Write of address 00427510<br>请求指教!我如何像厂商那样正常读取数据??请赋源码!!谢谢!!
 
Handle:=LoadLibrary('JBC_Attend.dll');这种东西搞一次就可以了,把Handle作为全局变量<br><br>前面两步都是用的今天连接,根本不需要loadlibrary的,后面的才需要<br><br>@ReadRam:=GetProcAddress(Handle,'ReadRam2k');<br>If @ReadRam&lt;&gt;nil then Begin<br> &nbsp; ReadRam(AD_ID,DataBuff,BlockFlag); &nbsp; &nbsp;<br><br>这个最经典了<br>http://www.delphibbs.com/delphibbs/dispq.asp?lid=2383995<br>标题: Delphi 中调用 VC 动态链接库 (100分)
 
调用DLL中的函数有两种方法;<br>第一种方法是静态调用,就如你的代码中所描述的一样,先声明函数 function Search(AR_ID:Integer):Integer; Stdcall external 'JBC_Attend.dll'name 'SearchAR';然后直接使用该函数即可;<br>第二种方法是动态调用,也如你代码中所描述一样,先加载DLL文件Handle:=LoadLibrary('JBC_Attend.dll'); 然后获得函数接口Search:=GetProcAddress(Handle,'SearchAR');<br>最后调用该函数。<br>一般而言,对DLL的调用采用上述方式中的一种即可。<br>你的问题出现在,你事先已经声明了函数Search,然后又在程序中对Search赋值(Search:=GetProcAddress(Handle,'SearchAR'))。
 
除了上面说的外,DataBuff要先分配空间才能接收数据回来吧<br>你这样试试<br> &nbsp; &nbsp;GetMem(DataBuff, 200);<br> &nbsp; &nbsp;try<br>   &nbsp;ReadRam(AD_ID,DataBuff,BlockFlag);<br>  finally<br> &nbsp; &nbsp; FreeMem(DataBuff);<br> &nbsp; &nbsp;end
 
非常謝謝你們:<br>我有兩個問題問您們<br><br>1:你的问题出现在,你事先已经声明了函数Search,然后又在程序中对Search赋值(Search:=GetProcAddress(Handle,'SearchAR'))。 <br>你講的問題是不是換個文件名即可<br>2:<br> &nbsp; GetMem(DataBuff, 200);<br> &nbsp; &nbsp;try<br>   &nbsp;ReadRam(AD_ID,DataBuff,BlockFlag);<br>  finally<br> &nbsp; &nbsp; FreeMem(DataBuff);<br> &nbsp; &nbsp;end <br>我不太明白這段,可不可以寫詳細點
 
关于第二就是先给你的接收变量分配一段空间嘛,如果你不这样做也可直接将<br>DataBuff:: array[0..1023] of char;这样就不用释放了,直接拿来用就可以了.<br>我调用DLL时常这么用的,你试试看呗<br>另外,实际上我看你调用DLL中的声明习惯我也不是很喜欢,通常的我会单独声明一个单元文件来对其进行声明,你可试一下这个工具的<br>http://vcl.vclxx.org/DELPHI/D32FREE/HEADCONV.ZIP<br>將 C/C++ 的 DLL 宣告檔轉換成 Object Pascal 的公用程式 ( 4.20 版 ),作者 : Dr. Bob
 
bulyn<br>您好:照您那麼說我如何改寫,只是換個名稱也不可以,我打开串口,搜索卡钟<br>沒問題,點機讀取數據時有問題<br>代碼如下<br>procedure TForm1.BitBtn3Click(Sender: TObject);<br><br>Var<br>ReadRam1:TReadRam2k;<br>Handle:THandle;<br>farfun: TFarProc;<br>AD_ID:Integer;<br>DataBuff: PChar;<br>BlockFlag:Integer;<br>begin<br> &nbsp; &nbsp; &nbsp; &nbsp;AD_ID:=1;<br> &nbsp; &nbsp; &nbsp; &nbsp;BlockFlag:=1;<br> &nbsp; &nbsp; &nbsp; &nbsp;Handle:=LoadLibrary('JBC_Attend.dll');<br> &nbsp; &nbsp; &nbsp; &nbsp;ReadRam1:=GetProcAddress(Handle,'ReadRam2k');<br> &nbsp; &nbsp; &nbsp; &nbsp;{If farfun&lt;&gt;nil then<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Begin<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@ReadRam:=farfun;}<br> &nbsp; &nbsp; &nbsp; &nbsp;ReadRam1(AD_ID,DataBuff,BlockFlag);<br> &nbsp; &nbsp; &nbsp; &nbsp;Edit3.Text:='記錄讀取中:'+DataBuff;<br> &nbsp; &nbsp; &nbsp; &nbsp;Edit4.Text:='讀取狀態'+IntToStr(ReadRam1(AD_ID,DataBuff,BlockFlag));<br><br> &nbsp; &nbsp; &nbsp; &nbsp;Memo1.Lines.Add(DataBuff);<br> &nbsp; &nbsp; &nbsp; // &nbsp; End;<br><br> &nbsp; &nbsp; &nbsp; // FreeLibrary(Handle);<br>End;<br><br>請指正
 
app2001:<br>您好!<br>改成那樣(DataBuff:: array[0..1023] of char;)調試通不過,dll 要求的是pchar類型.可否或多寫些代碼給我看看.謝謝!請指正
 
app2001:<br>您好:<br>HEADCONV 怎麼樣用阿!是運行 HCWIZARD嗎?我怎樣選擇我的 dll 文件阿! 謝謝
 
上面说的很对,dll调用时,要么用静态的,要么用动态的,两种混在一起容易出错。<br>用静态那么你在BitBtn1Click里就不用Handle:=LoadLibrary('JBC_Attend.dll');<br>farfun:=GetProcAddress(Handle,'ReadRam2k');……等了,直接使用ReadRam2k<br>这个函数。<br>用动态在implementation里不要申明函数<br>function Open_ComX(Comport:PChar;Band:Integer):Integer; Stdcall external 'JBC_Attend.dll'name 'Open_ComX';<br>在BitBtn1Click里用Handle:=LoadLibrary('JBC_Attend.dll');<br>farfun:=GetProcAddress(Handle,'ReadRam2k');……<br><br>对于databuff还是建议使用getmen的方法来申请一块内存空间,当然申请的空间不能比实际的小不让还是有错,最后要释放内存。<br><br>其实前面几位说的比较清楚了,自己多琢磨一下吧。
 
多人接受答案了。
 
后退
顶部