遇到难题了,请大家指教。虚心学习中...调用一个动态库。(300分)

  • 主题发起人 主题发起人 1111
  • 开始时间 开始时间
1

1111

Unregistered / Unconfirmed
GUEST, unregistred user!
遇到难题了,请大家指教。虚心学习中...调用一个动态库。原来是用C调用的,主要是DLL中的函数不会用。这里有一个PDF文档和DLL,大家发邮件到SUNPLAY@263.NET,我给您回复。大家帮着看一看。另外,这些资料也会有用。是一个采集器的接口函数<br><br>我敲一些代码,大家看一看。<br>[calling sequence]<br>&nbsp; &nbsp; int lm_open();<br>[parameters]<br>&nbsp; &nbsp; none<br>[return values]<br>&nbsp; &nbsp; lm_success<br>&nbsp; &nbsp; lm_er_nolmwin<br>&nbsp; &nbsp; lm_er_wrongver<br><br><br>C语言的调用代码<br><br><br>......<br>int ret,connum;<br>if((ret=lm_open()) !=lm_success) <br>{<br>&nbsp; &nbsp; if (ret==lm_er_wrongver)<br>&nbsp; &nbsp; &nbsp; &nbsp;printf("wrong lmwin version!!!/n");<br>&nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp;printf(no lmwin!!!/n);<br>&nbsp; &nbsp; return;<br>}
 
更详细的资料是一个PDF文档和一个DLL。您留下EMAIL,我给您发。<br>难者不会,会者不难。我刚接手DLL这一块。今年刚毕业。大家帮帮忙。
 
Im_a_wolf@sohu.com<br>不过说好了,不一定能帮你弄出来!
 
Delphi中DLL的创建和使用<br>&nbsp;<br>1.DLL简介; 2.调用DLL; 3.创建DLL; 4.两个技巧; 5.初始化; 6.例外处理。 <br>&nbsp;<br><br>1、DLL简介<br>  DLL是Dynamic-Link Libraries(动态链接库)的缩写,库里面是一些可执行的模块以及资源(如位图、图标等)。可以认为DLL和EXE基本上是一回事,只是DLL不能直接执行,而必须由应用程序或者其他DLL调用。DLL为应用程序间的资源共享提供了方便,同时也是多语言混合编程的重要手段。由此可见学习使用DLL是Windows程序员必须掌握的一项重要技术。<br><br>&lt;Back to Top&gt;<br><br>&nbsp;<br><br>2、如何调用DLL<br>  在Delphi中有两种方法调用DLL中的函数和过程,即外部声明或者动态加载。<br><br>&lt;1&gt;外部声明<br>  在Delphi中外部声明是访问外部例程最容易和最常用的方式,有两种声明方式:通过名字、通过索引号。举例如下:在MYDLL.DLL中有两个函数和一个过程,则其外部声明可以写成:<br><br>function test1:integer;external 'mydll';<br>//直接通过名称调用test1(注意名称大小写敏感)。 <br>function test11:integer;external 'mydll' name 'test1';<br>//通过名称调用test1,在程序中使用新名称(原名称仍然大小写敏感)。 <br>procedure test2;external 'mydll' index 1;<br>//通过索引号调用TEST2。程序中可以用与DLL中不一样的名称. <br>  使用外部声明的缺点是程序启动时如果找不到mydll.dll将无法运行,即使没有调用其中的模块。 动态加载的方法可以避免这种情况。<br><br>&lt;2&gt;动态加载<br>  通过调用Windows API中的相关函数,将DLL调入内存并获得指向函数或过程的指针,执行完模块后释放内存。除了节约内存外,这种方法的一个很大的优点是能处理找不到dll或者在装入过程中出错的情况。这样即使某个dll有问题,应用程序的其他部分仍然能够正常运行。动态加载的例子如下:<br><br>var hDll:THandle;<br>  Test1:function:integer;<br>begin<br>  hDll:=LoadLibrary('mydll.dll');<br>  if hDll&lt;32 then exit;//如果Dll无法加载则跳出<br>  @Test1:=GetProcAddress(hDll,MakeIntResource(1));<br>    //取得mydll中的第一个函数的地址。<br>  ...<br>  FreeLibrary(hDll);<br>end; <br><br>&lt;Back to Top&gt;<br><br>&nbsp; <br><br>3、用Delphi创建DLL<br>  用Delphi创建一个DLL是十分简单的,首先需要新建一个DLL的Porject(如果使用Delphi3.0则可以在File-&gt;New对话框中选择DLL),当然也可以自己写,现在这个Project是这样的:<br><br>library Project1;<br>uses SysUtils,Classes;<br>begin<br>end. <br><br>  当然这是一个空DLL,现在让我们来加入一个函数,让他成为我们的第一个可以使用的DLL。完成后的文件是这样的:<br><br>library dll1;<br>uses SysUtils,Classes;<br><br>function Test1(a,b:integer):integer;<br>begin<br>Result:=a+b;<br>end;<br><br>exports<br>Test1 index 1;<br><br>begin<br>end. <br><br>  在这个DLL里我们声明了一个加法函数,然后用exports语句输出它,只有被输出的函数或过程能被其他程序调用。exports语句后的语法是:函数名 [index &lt;n&gt;],index &lt;n&gt;是为函数手工指定索引号,以便其他程序确定函数地址;也可以不指定,如果没有使用Index关键字,Delphi将按照exports后的顺序从1开始自动分配索引号。现在我们可以调用这个DLL了,下面给出一个实例,运行后form1的标题将变成“1+2=3”:<br><br>声明部分:function Test1(a,b:integer):integer;external 'dll1';<br>       注意此处是大小写敏感的。<br>运行部分:form1.caption:='1+2='+inttostr(test1(1,2)); <br><br>&lt;Back to Top&gt;<br><br>&nbsp; <br><br>4、使用DLL的两个技巧<br>&lt;1&gt;把现有的项目改成DLL<br>  学会制作DLL以前,大多数程序员手中都积攒下来不少已经完成了的项目,如果现在需要把这些项目做成DLL而不是可执行文件,重新写一遍显然是没有必要的,只要按照下面的步骤对已有的项目文件进行修改就可以了:<br>  ① 打开项目文件(.DPR),删除单元底部begin和end.之间的所有语句(一般情况下这些语句是由Delphi自动生成的)。如果项目中没有用到Form,则从uses子句中删除表单单元(Form),然后转到第③步。<br>  ② 对项目进行修改,令除Main Form之外的所有Form都是动态生成的,这样我们只要在DLL输出的一个函数或者过程中生成Main Form,即可调用执行整个项目。我们假设Main Form的名字是MyMainForm,项目的名字是MyDll,现在在单元底部的begin语句之前加入一个过程,过程的名字为RunMyDll,这个过程将动态生成Main Form,从而运行整个项目。RunMyDll的写法如下:<br>    procedure InitDll2;<br>    begin<br>    Application.CreateForm(TMyMainForm, MyMainForm);<br>    MyMainForm.Show; //如果MyMainForm不可视则需要这一句.<br>    end;<br>  ③ 如果想要输出其他函数或者过程,而原来的项目中没有,则可以在单元底部的begin语句之前加入这些代码。<br>  ④ 在单元底部的begin语句之前加入一个exports小节,然后写出所有想要输出的函数或过程的名字(最好指定索引号)。注意如果执行了第②步,一定要输出RunMyDll过程。<br>  ⑤ 将项目文件顶部的保留字program改为library。<br>  ⑥ 编译。<br>  现在就可以在其他程序中调用本项目中的函数和过程了,只要执行RunMyDll就可以执行这个项目,和执行原来的可执行文件一模一样。<br><br>&lt;2&gt;创建一个引入文件<br>  如果DLL比较复杂,则为它的声明专门创建一个引入程序单元将是十分有意义的,并且会使这个DLL变得更加容易维护。引入单元的格式如下:<br>  unit MyImport; {Import unit for MyDll.Dll}<br>  interface<br>  procedure RunMyDll;<br>  implementation<br>  procedure RunMyDll;external 'MyDll' index 1;<br>  end.<br>这样以后想要使用MyDll中的例程时,只要简单的在程序模块中的uses子句中加上MyImport即可。<br><br>&lt;Back to Top&gt;<br><br>&nbsp; <br><br>5、DLL的初始化和善后工作<br>  一般的DLL不需要做初始化和善后工作,因此大部分读者可以跳过这一节。但如果你想让你的DLL在被载入时先作一些初始设定,或者退出时释放资源,则可以有三种方法达到目的:<br><br>&lt;1&gt;利用Unit的Initalization与Finalization这两个小节<br>  可以在Unit的这两个小节中安排Unit的进入和退出,但是Program与Library并没有这两个部分,所以只能写在Unit中。<br><br>&lt;2&gt;利用ExitProc变量<br>  在Library的begin..end.中间是可以写代码的,这里可以放置DLL初始化代码。如果想要做善后工作,则可以利用ExitProc变量。我们首先在初始化代码中把ExitProc中包含的默认的善后过程地址保存下来,然后把自定义的过程的地址赋给它,这样DLL退出时就会执行我们制定的程序;在自定义的过程的最后,把ExitProc恢复原来的默认值,以便DLL能够继续完成原来默认的善后工作。下面是示例:<br>  library MyDLL;<br>  ...<br>  OldExitProc: pointer;<br>  ...<br>  procedure MyExitProc;<br>  begin<br>  ... //善后程序<br>  ExitProc := OldExitProc;<br>  end;<br>  ...<br>  begin<br>  ... //初始化程序<br>  OldExitProc := ExitProc;<br>  ExitProc := @MyExitProc;<br>  end.<br><br>&lt;3&gt;利用DllProc变量<br>  和ExitProc一样,DllProc也是一个在Systemd单元中预定义的变量。在使用DLLProc时, 必须先写好一个具有以下原型的程序:<br>  procedure DLLHandler(Reason: integer);<br>并在library的begin..end.之间, 将这个DLLHandler程序的执行地址赋给DLLProc中, 这时就可以根据参数Reason的值分别作出相应的处理。另外注意要将Windows单元加入uses子句。示例如下:<br>  library TestDLL;<br>  ...<br>  procedure MyDLLHandler(Reason: integer);<br>  begin<br>   case Reason of<br>    DLL_Process_Attach: //整个DLL的初始化代码<br>    DLL_Process_Detach: //整个DLL的善後程序<br>    DLL_Thread_Attach: //当主叫端开始一个Thread时<br>    DLL_Thread_Detach: //当主叫端终止一个Thread时<br>   end;<br>  end;<br>  ...<br>  begin<br>  ... //初始化代码<br>  DLLProc := @MyDLLHandler;<br>  MyDLLHandle(DLL_Process_Attach);<br>  end.<br>由上例可以知道,当DLL支援多进程(Thread)的处理时, DllProc非常适合使用。<br><br>&lt;Back to Top&gt;<br><br>&nbsp; <br><br>6、DLL中的例外处理<br>  在用Delphi制作DLL时, 在例外处理方面请留意以下三点: <br><br>如果uses子句中没有SysUtils话,无法使用例外处理。 <br>如果DLL中没有对例外进行处理的话,这个例外会想完传导到主叫端的应用程序。如果该应用程序也是Delphi写的话, 这个例外可以由主叫端进行处理。 <br>承上, 如果主叫端的程式不是Delphi或Borland C++ Builder,则例外以作业系统错误的形式来处理,例外编号是$0EEDFACE,ExceptionInformation中第一个进入点是例外发生的地址,第二个进入点是指向的Delphi例外物件的引用。 <br>&lt;Back to Top&gt; &nbsp;<br><br><br><br>本文参考了钱达智先生(Wolfgang Chien)的技术文章,以及《Delphi for Windows Power Toolkie》([美]Harold Davis著) <br>
 
谢谢两位。<br>&nbsp;TO Rudder 邮件已发<br>&nbsp;TO BOOK523 代码我要仔细看<br><br>谢谢。
 
懂行的朋友帮帮忙,按说这是小问题。只是我接触的少而工作又很紧。谢谢各位。<br><br><br>[calling sequence]<br>&nbsp; &nbsp;int lm_open();<br>[parameters]<br>&nbsp; &nbsp;none<br>[return values]<br>&nbsp; &nbsp;lm_success<br>&nbsp; &nbsp;lm_er_nolmwin<br>&nbsp; &nbsp;lm_er_wrongver<br><br><br>C语言的调用代码<br><br><br>......<br>int ret,connum;<br>if((ret=lm_open()) !=lm_success) <br>{<br>&nbsp; &nbsp;if (ret==lm_er_wrongver)<br>&nbsp; &nbsp; &nbsp; printf("wrong lmwin version!!!/n");<br>&nbsp; &nbsp;else<br>&nbsp; &nbsp; &nbsp; printf(no lmwin!!!/n);<br>&nbsp; &nbsp;return;<br>}
 
我把你两个函数翻译成delphi的<br>function lm_open:integer;external 'Yourdll' name 'lm_open';<br>const<br>&nbsp; lm_success= &nbsp; <br>&nbsp; lm_er_nolmwin=<br>&nbsp; lm_er_wrongver= //实际等于多少要看你的技术手册<br><br><br>var<br>&nbsp;i:integer;<br>begin <br>&nbsp; &nbsp;i:=lm_open;<br>&nbsp; &nbsp;if i&lt;&gt;lm_success then<br>&nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp;if (i=lm_er_wrongver) then<br>&nbsp; &nbsp; &nbsp; &nbsp; showmessage('wrong lmwin version!!!')<br>&nbsp; &nbsp; &nbsp;else<br>&nbsp; &nbsp; &nbsp; &nbsp; showmessage('no lmwin!!!');<br>&nbsp; &nbsp; &nbsp;Abort; &nbsp; &nbsp;<br>&nbsp; &nbsp;end;<br>end;<br><br>
 
谢谢楼上的。我学习一下。
 
谢谢book523<br>这个问题搞了一段时间还没搞定,最后判定这个DLL有些问题。偶另找了一个。而且还有代码。是VB的。一会我贴在下面。那位朋友能指导我一下。分数送上。<br>Dim com As Integer<br>Dim i As Integer<br>Dim j As Integer<br>Dim k As Integer<br>Dim m As Integer<br>Dim InitTbl1 As INITTBL<br>Dim getinf As CINFTBL<br>Dim ret As Integer<br>Dim fname As String<br>Dim str As String<br><br>Private Sub Combo1_Click()<br>com = Combo1.ListIndex<br>End Sub<br>Private Sub Command1_Click()<br>&nbsp; &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp; <br>Dim a1 As Long<br>Dim a2 As Long<br>m = 0<br>j = 0<br>ret = 0<br>InitTbl1.speed = 7<br>InitTbl1.length = 0<br>InitTbl1.parity = 0<br>InitTbl1.sbit = 1<br>InitTbl1.ptout = 100<br>InitTbl1.ctout = 1000<br>InitTbl1.cretry = 99<br>InitTbl1.stopkey1 = 2<br>InitTbl1.stopkey2 = 0<br>ret = hst_open(com, InitTbl1)<br>If ret &lt;&gt; 0 Then<br>&nbsp; &nbsp; &nbsp; MsgBox ("通信口打开出错!")<br>&nbsp; &nbsp; &nbsp; ret = hst_close()<br>Else<br>&nbsp; &nbsp; &nbsp; ret = 0<br>&nbsp; &nbsp; &nbsp; ret = hst_idtblclr()<br>&nbsp; &nbsp; &nbsp; If ret &lt;&gt; 0 Then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MsgBox ("文件列表无法清空!")<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;j = 1<br>&nbsp; &nbsp; &nbsp; End If<br>&nbsp; &nbsp; &nbsp; ret = 0<br>&nbsp; &nbsp; &nbsp; ret = hst_idtbladd("&amp;&amp;&amp;&amp;&amp;&amp;")<br>&nbsp; &nbsp; &nbsp; If ret &lt;&gt; 0 And j = 0 Then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MsgBox ("文件列表添加出错!")<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;j = 1<br>&nbsp; &nbsp; &nbsp; End If<br>&nbsp; &nbsp; &nbsp; ret = 0<br>&nbsp; &nbsp; &nbsp; ret = hst_polling(1, 1)<br>&nbsp; &nbsp; &nbsp; If ret &lt;= 0 And j = 0 Then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MsgBox ("无法侦听通信信息!")<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;j = 1<br>&nbsp; &nbsp; &nbsp; End If<br>&nbsp; &nbsp; &nbsp; i = 0<br>&nbsp; &nbsp; &nbsp; ret = 0<br>&nbsp; &nbsp; &nbsp; If i = 0 Then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ret = hst_getcinffirst(getinf)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;i = 1<br>&nbsp; &nbsp; &nbsp; Else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ret = hst_getcinfnext(getinf)<br>&nbsp; &nbsp; &nbsp; End If<br>&nbsp; &nbsp; &nbsp; If ret &lt;&gt; 0 Then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MsgBox ("没有获得侦听结果!")<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;j = 1<br>&nbsp; &nbsp; &nbsp; Else<br>&nbsp; &nbsp; &nbsp; pname = Text1.Text<br>&nbsp; &nbsp; &nbsp; pname1 = pname + "/apsmp.mot"<br>&nbsp; &nbsp; &nbsp; pname2 = pname + "/apsmp.map"<br>&nbsp; &nbsp; &nbsp; getinf.filesize = FileLen(pname1) + FileLen(pname2)<br>&nbsp; &nbsp; &nbsp; pname = pname + "/apsmp.*"<br>&nbsp; &nbsp; &nbsp; getinf.fileno = 2<br>&nbsp; &nbsp; &nbsp; ret = 0<br>&nbsp; &nbsp; &nbsp; k = 1<br>&nbsp; &nbsp; &nbsp; Label5.Caption = "******正在传输****** &nbsp; &nbsp; &nbsp; "<br>&nbsp; &nbsp; &nbsp; ret = hst_filesend(pname, getinf)<br>&nbsp; &nbsp; &nbsp; Label5.Caption = "欢迎使用CASIO DT-900"<br>&nbsp; &nbsp; &nbsp; If ret = 0 And j = 0 Then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;k = 0<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MsgBox ("应用程序安装完毕!")<br>&nbsp; &nbsp; &nbsp; Else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MsgBox ("程序传输错误!")<br>&nbsp; &nbsp; &nbsp; End If<br>&nbsp; &nbsp; &nbsp; End If<br>&nbsp; &nbsp; &nbsp; ret = 0<br>&nbsp; &nbsp; &nbsp; ret = hst_close()<br>&nbsp; &nbsp; &nbsp; If ret &lt;&gt; 0 Then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MsgBox ("通信口无法关闭!")<br>&nbsp; &nbsp; &nbsp; End If<br>End If<br>End Sub
 
多人接受答案了。
 
后退
顶部