参考:http://blog.csdn.net/ninetowns2008/article/details/6311663

结合这篇博客:http://www.cnblogs.com/xumenger/p/4372289.html

再结合:http://blog.csdn.net/lailai186/article/details/8770487

1.DLL简介;2.调用DLL;3.创建DLL;4.两个技巧;5.初始化;6.例外处理

1.DLL简介

  DLL是Dynamic-Link Libraries(动态链接库)的缩写,库里面是一些可执行的模块以及资源(如:位图、图标……)。可以认为DLL和EXE基本上是一回事,只是DLL不能直接执行,而必须通过应用程序或者其他DLL调用。

  DLL为应用程序间的资源共享提供了方便,同时也是多种语言混合编程的重要手段。由此可见学习使用DLL是Windows程序员必须掌握的一项重要技术

2.如何调用DLL

在Delphi中有两种方法调用DLL中的函数和过程,即外部声明或动态加载

  <1>外部声明

  在Delphi中外部声明时访问外部例程最容易和最常用的方式,有两种声明方式:通过名字、通过索引号。举例如下:在MYDLL.DLL中有两个函数和一个过程,则其外部声明可以写成

  1. function test1: Integer; external 'mydll'; //或者external 'mydll.dll';
  2. //直接通过名称调用test1(注意名称大小写敏感)
  3.  
  4. function test11: Integer; external 'mydll' name 'test1';
  5. //通过名称调用test1,在程序中使用新名称(原名称仍然大小写敏感)
  6.  
  7. procedure test2; external 'mydll' index 1;
  8. //通过索引号调用TEST2。程序中可以使用与DLL中不一样的名称

  使用外部声明的缺点是程序启动时如果找不到mydll.dll将无法运行,即使没有调用其中的模块。动态加载的方法可以避免这种情况

  <2>动态加载

  通过调用Windows API中的相关函数,将DLL调入内存并获得指向函数或过程的指针,执行完模块后释放内存。除了节约内存之外,这种方法的很大的优点是能处理找不到dll或者装入过程中出错的情况。这样即使某个dll有问题,应用程序的其他部分仍然能够正常运行。动态加载的例子如下

  1. var hDll : THandle;
  2. Test1 : function : integer;
  3. begin
  4. hDll := LoadLibrary('mydll.dll');  //注意LoadLibrary函数的参数是一个PChar类型的,不是string,该参数是指要加载的DLL的DLL名
  5. if hDll < 32 then
  6. exit; //如果Dll无法记载则跳出
  7. @Test1 := GetProcAddress(hDll, MakeIntResource(1));  //取得mydll.dll中的第一个函数的地址。
  8. //取得mydll 中的第一个函数的地址
  9.  
  10. ....
  11. FreeLibrary(hDll);
  12. end;

  

3.用Delphi创建DLL

  用Delphi创建一个DLL是十分简单的,首先需要新建一个DLL的Project(如果使用Delphi3.0则可以在File->New对话框中选择DLL),当然也可以自己写,现在这个Project是这样的

  1. library Project1;
  2. uses SysUtils, Classes;
  3. begin
  4. end.

  当然这是一个空的DLL,现在让我们来加入一个函数,让它成为我们的第一个可以使用的DLL。完成后的文件是这样的

  1. library dll1;
  2. uses SysUtils, Classes;
  3.  
  4. function Test1(a, b: Integer): Integer;
  5. begin
  6. Result := a+b;
  7. end;
  8.  
  9. exports
  10. Test1 index 1;
  11.  
  12. begin
  13. end.

  在这个DLL里我们声明了一个加法函数,然后用exports语句输出它,只有被输出的函数或过程才能被其他程序调用。exports语句的语法是

  1. exports
  2. 函数名 [index <n>];

  index<n>是为函数手工指定索引号,以便其他程序确定函数地址;也可以不指定,如果没有使用index 关键字,Delphi将按照exports 后的顺序从1开始自动分配索引号。现在我们可以调用这个DLL了,下面给出一个实例,运行后form1 的标题将变成 1+2=3

  1. //声明部分
  2. function Test1(a, b: Integer): Integer; external 'dll1'; //注意此处是大小写敏感的
  3.  
  4. //运行部分
  5. form1.caption := '1+2=' + IntToStr(test1(1,2));

  

4.使用DLL的两个技巧

  <1>把现有的项目改成DLL

  学会制作DLL之前,大多数程序员手中都积攒下来不少已经完成的项目,如果现在需要把这些项目做成DLL而不是可执行文件,重新写一遍显然是没有必要的,只要按照下面的步骤对已有的项目文件进行修改就可以了

    (1)打开项目文件(.DPR),删除单元底部 begin 和 end. 之间的所有语句(一般情况下这些语句是有Delphi 自动生成的)。如果项目中没有用到Form,则从uses 子句中删除表单单元(Form),然后转向(2)

    (2)对项目进行修改,令除了 Main Form之外的所有Form 都是动态生成的,这样我们只要在DLL 输出的一个函数或过程中生成Main Form,即可调用执行整个项目。我们假设Main Form的名字是MyMainForm,项目的名字是MyDll,现在在单元底部的begin语句加入之前加入一个过程,过程的名字是RunMyDll,这个过程动态生成Main Form,从而运行整个项目。RunMyDll的写法如下

  1. procedure InitDll2;
  2. begin
  3. Application.CreateForm(TMyMainForm, MyMainForm);
  4. MyMainForm.Show; //如果MyMainForm不可视就不用加这一句
  5. end;

    (3)如果想要输出其他函数或者过程,而原来的项目中没有,则可以在单元底部的begin语句之前加上这些代码

    (4)在单元底部的begin 语句之前加上一个 exports小节,然后写出所有想输出的函数或过程的名字(最好指定索引号)。注意如果执行了第(2)补,一定要输出 RunMyDll的过程

    (5)将项目文件顶部的保留字program改为library

    (6)编译

    现在就可以在其他程序中调用本项目中的函数和过程了,只要执行 RunMyDll 就可以执行这个项目,和执行原来的可执行文件一模一样

  <2>创建一个引入文件

  如果DLL比较复杂,则为它的声明专门创建一个引入程序单元将是十分有意义的,并且会使这个DLL变得更加容易维护。引入单元的格式如下

  1. unit MyInport; {Import unit for MyDll.Dll}
  2. interface
  3. procedure RunMyDll;
  4. implementation
  5. procedure RunMyDll; external 'MyDll' index 1;
  6. end.

  这样以后想要使用MyDll的例程时,只要简单的在程序模块中的uses子句中加上 MyImport就可以了

5.DLL的初始化和善后工作

一般的DLL不需要做初始化和善后工作。但是如果你想让你的DLL在被载入时先设定一些初始设定,或者退出时释放资源,则可以有三种方法达到目的

  <1>利用在 Unit 的Initialization 与 Finalization这两个小节

    可以在Unit的这两个小节里安排Unit 的进入和退出,但是 Program 与 Library并没有这两个部分,所以只能写在Unit里面

  <2>利用 ExitProc 变量

    在Library 的begin .. end.中间是可以写代码的,这里可以放置DLL初始化代码。如果想要做善后工作,则可以利用ExitProc 变量。我们首先在初始化代码中把 ExitProc中包含的默认的善后过程地址保存下来,然后把自定义的过程的地址赋给他,这样DLL退出时就会执行我们制定的程序;在自定义的过程的最后,把ExitProc恢复原来的默认值,以便DLL 能股继续完成原来默认的善后工作。下面是示例

  1. library MyDLL;
  2. ...
  3. OldExitProc : pointer;
  4. ...
  5. procedure MyExitProc;
  6. begin
  7. ...//善后程序
  8. ExitProc := OldExitProc;
  9. end;
  10. ...
  11. begin
  12. ...//初始化程序
  13. OldExitProc := ExitProc;
  14. ExitProc := @MyExitProc;
  15. end.

     以上的代码同样是关于Delphi的指针和函数指针的一个很好的应用的例子,值得研究一下

  <3>利用DllProc变量

    和ExitProc 一样,DllProc也是一个在Systemd单元里预定义的变量。在使用DLLProc时,必须先写好一个具有以下原型的程序:  骗人哦测读热 DLLHandler(Reason : Integer);

    并在Library 的 begin ... end.之间,将这个DLLHandle程序的执行地址赋值给DLLProc,这时候就可以根据参数Reason的值分别作出相应的处理。另外注意将 windows单元加入uses子句中。示例

  1. library TestDLL;
  2. ...
  3. procedure MyDLLHandler(Reason : Integer);
  4. begn
  5. case Reason of
  6. DLL_Process_Attach; //整个DLL的初始化代码
  7. DLL_Process_Detach; //整个DLL的善后程序
  8. DLL_Thread_Attach; //当主叫端开始一个Thread时
  9. DLL_Thread_Detach; //当主叫端终止一个Thread时
  10. end;
  11. end;
  12. ...
  13. begin
  14. .. //初始化代码
  15. DLLProc := @MyDLLHandler;
  16. MyDLLHandler(DLL_Process_Attach);
  17. end;

     由上例可知,当DLL支持多进程的处理是,DLLProc非常适合使用

6.DLL中的例外处理

  在用Delphi制作DLL的时候,在例外处理方面请注意以下三点

    <1>如果uses子句中没有SysUtils的话,无法使用例外处理

    <2>如果DLL中没有对例外进行处理的话,这个例外会向外传导到主叫端的应用程序。如果该应用程序也是Delphi写的话,这个例外可以由主叫端进行处理

    <3>承上,如果主叫端的程序不是Delphi 或Borland C++ Builder,则例外以作业系统错误的形式来处理,例外编号是$0EEDFACE,ExceptionInformation中地第一个进入点是例外发生的地址,第二个进入点是指向Delphi 例外物件的引用

Delphi中DLL的创建和使用的更多相关文章

  1. Delphi中DLL的创建和使用(转)

    Delphi中DLL的创建和使用     1.DLL简介:   2.调用DLL:   3.创建DLL:   4.两个技巧:   5.初始化:   6.例外处理.            1.DLL简介  ...

  2. 有谁知道Delphi中"窗口"的创建过程?

      求助:有谁知道Delphi中窗口的创建过程,此“窗口”不仅仅指 TForm 类型, 还包括一般的窗口控件,如TButton,TEdit等等,希望有能够十分详细的运作 过程,比如说CreatPara ...

  3. delphi中DLL编程详解

    10.1 Windows的动态链接库原理 动态链接库(DLLs)是从C语言函数库和Pascal库单元的概念发展而来的.所有的C语言标准库函数都存放在某一函数库中,同时用户也可以用LIB程序创建自己的函 ...

  4. delphi 中DLL的建立

    Dll的创建与调用   File ->New->Other->Dll Wizard  DLL的创建 //可以将本代码复制粘贴到项目中 library Project1; uses S ...

  5. Delphi中的窗体创建与销毁

    Delphi中的窗体,有模式窗体与非模式窗体两种.两种窗体的调用方式不同,模式窗体使用ShowModal显示,非模式窗体使用Show显示.当显示模式窗体的时候你是不能操作本程序的其他窗体的,你不能把焦 ...

  6. Delphi中DLL的其他应用

    http://blog.csdn.net/zhenghui1/article/details/6618273 1.DLL的入口函数和出口函数 在编写DLL时可以在DLL项目文件的begin..end之 ...

  7. 且看一文梳理VS2019中dll的创建使用

    动态链接库(dll) Windows下有静态链接(lib)库和动态链接库(dll)两种共享代码的方式. 本文将介绍dll的应用场景,以及在vs2019平台下的生成和使用. 今天的笔记内容说的是平时经常 ...

  8. Delphi中DLL初始化和退出处理

    来自delphibbs: zhousy_2000, 时间: 2005-09-13 13:53:00, ID: 3203484 <1>利用Unit的Initalization与Finaliz ...

  9. 在Delphi中如何动态创建dbf数据库(二)?

    unit Form_ToChangCSVforDBFU; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics ...

随机推荐

  1. OpenCV图像轮廓检测

    轮廓检测: 轮廓检测的原理通俗的说就是掏空内部点,比如原图中有3*3的矩形点.那么就可以将中间的那一点去掉. 一.关键函数1.1  cvFindContours函数功能:对图像进行轮廓检测,这个函数将 ...

  2. BZOJ 1670: [Usaco2006 Oct]Building the Moat护城河的挖掘

    Description 求凸包周长. Sol 凸包+计算几何. 这好像叫什么 Graham Scan 算法... 这个可以求凸包的周长,直径,面积. 选择一个基点,然后按极角排序,最后用一个栈一直维护 ...

  3. Android的一种MVP模式框架

    今天给大家分享的是一种将view的初始化和逻辑与activity分离的架构,采用的是mvp模式.但令人遗憾的是,这仅仅是一个新的思路,我在实际使用中发现其并不能完全将UI逻辑与activity分开,所 ...

  4. 二分图水一波~~~~d带你飞

    Current Time: 2016-03-11 17:45:36 Contest Type: Public Start Time: 2016-03-04 13:00:00 Contest Statu ...

  5. Python自动化之面向对象进阶

    1 静态方法 静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法. class Dog(ob ...

  6. java对txt文件内容追加

    package com.test; import java.io.FileOutputStream; /** * 对txt文件在文本追加内容 * @author Wdnncey * */ public ...

  7. POI文件导出至EXCEL,并弹出下载框

    相关参考帖子 : [1]http://www.tuicool.com/articles/MnqeUr [2]http://www.oschina.net/question/253469_51638?f ...

  8. UNIX进程

    UNIX进程控制的博客   http://blog.csdn.net/yang_yulei/article/details/17404021 Linux的概念与体系    http://www.cnb ...

  9. 【leetcode】Text Justification

    Text Justification Given an array of words and a length L, format the text such that each line has e ...

  10. ACM/ICPC 之 Prim范例(ZOJ1586-POJ1789(ZOJ2158))

    两道Prim解法范例题型,简单的裸Prim,且两题相较以边为重心的Kruskal解法而言更适合以点为重心扩展的Prim解法. ZOJ1586-QS Network 题意:见Code 题解:直接的MST ...