[转]Delphi DLL的创建、静态 以及动态调用
第一章 DLL简单介绍
由于在目前的学习工作中,需要用到DLL文件,就学习了下,在这里作个总结。
首先装简单介绍下DLL:
1,减小可执行文件的大小
DLL技术的产生有很大一部分原因是为了减小可执行文件的大小。当操作系统进入Windows时代后,其大小已经达到几十兆乃至几百兆。试想如果还是使用DOS时代的单执行文件体系的话一个可执行文件的大小可能将达到数十兆,这是大家都不能接受的。解决的方法就是采用动态链接技术将一个大的可执行文件分割成许多小的可执行程序。
2,实现资源共享
这里指的资源共享包括很多方面,最多的是内存共享、代码共享等等。DLL还有一个突出的特点就是在内存中只装载一次,这一点可以节省有限的内存,而且可以同时为多个进程服务。
3,便于维护和升级
在软件运行出现问题的时候,我们并不需要重新安装程序,只需要替换相应的DLL文件即可。
4,比较安全
这里说的安全也包括很多方面。比如,DLL文件遭受病毒的侵害机率要比普通的EXE文件低很多。另外,由于是动态链接的,这给一些从事破坏工作的“高手”们多少带来了一些反汇编的困难。
第二章 在Delphi中编写DLL文件
编写DLL文件其实不是什么困难的事情,和我们平时在Delphi中编写程序基本相似,下面先以一个简单的例子来说明。
- library DLL;
- { Important note about DLL memory management: ShareMem must be the
- first unit in your library's USES clause AND your project's (select
- Project-View Source) USES clause if your DLL exports any procedures or
- functions that pass strings as parameters or function results. This
- applies to all strings passed to and from your DLL--even those that
- are nested in records and classes. ShareMem is the interface unit to
- the BORLNDMM.DLL shared memory manager, which must be deployed along
- with your DLL. To avoid using BORLNDMM.DLL, pass string information
- using PChar or ShortString parameters. }
- uses
- ShareMem,
- SysUtils,
- Classes;
- function testStr: TStringList; stdcall;
- var
- str: string;
- strlist: TStringList;
- begin
- strlist := TStringList.Create;
- strlist.Add('hello');
- strlist.Add('world');
- str := 'hello world';
- result := strlist;
- end;
- function testInt(i: Integer): Integer; stdcall;
- begin
- Inc(i);
- result := i;
- end;
- {$R *.res}
- exports
- testStr,
- testInt;
- begin
- end.
可以看出在上面的Dll文件中我们封装了两个函数。跟一般Delphi编写的程序基本相同,只是在DLL文件中的函数后面多了一个stdcall参数,并且用exports声明需要引出的函数。只要编译上述代码就可以得到一个动态链接库的Dll文件。
1,在Dll中编写的函数必须在后面加上stdcall调用参数,如果忘记添加stdcall参数的话虽然编译可以通过,但在调用这个DLL时会出现很严重的错误,导致操作系统的死锁。
2,所写的函数和过程必须用exports声明为外部函数。若没有声明,那Dll内部的函数是不可调用的,这一点显然不是我们想看到的。
3,当使用了长字符串类型的参数、变量时,如string,要引用ShareMem。虽然Delphi中的string功能很强大,但若是您编写的Dll文件要供其它编程语言调用时,最好使用PChar类型。如果您要坚持使用string类型的参数时、变量甚至是记录信息时,就要引用ShareMem单元,而且这个单元必须是第一个引用的,即在uses语句后的第一个单元。如下:
- uses
- ShareMem,
- SysUtils,
- Classes;
另外,还有一个地方我们需要添加ShareMem单元,即在您的工程文件中(*.dpr)中的uses下第一个引用ShareMem单元。这里需要注意的是在*.dpr文件中而不是单元文件(*.pas)中添加相同的单元,这一点Delphi自带的帮助文件没有说清楚,造成了许多误会。若不这样做的话,您可能付出死机的代价。避免使用string类型的方法是将其转换为PChar或ShortString类型。
第三章 Dll文件的调用
一,静态调用
调用Dll文件要比编写Dll容易多了,这里先总结一下Dll的静态调用。首先看下面的小例子:
- function testInt(i: Integer): Integer; stdcall; external 'DLL.dll';
- procedure TForm1.btn2Click(Sender: TObject);
- begin
- showMessage(inttostr(testInt(1)));
- end;
大家可以看到我们做的唯一的工作是将Dll中的函数说明放在implementation下(或是放在文件单元的var下),并且用external语句指定了Dlll的位置。这样我们就可以直接使用Dll中的函数了。
1,调用参数stdcall,在引用Dll中的函数时也要使用stdcalll参数。
2,用external声明Dll文件的位置。注意文件的后缀名必须加上。
3,不能从Dll中调用全局变量。如果我们在DLL中声明了某种全局变量,如:var s:byte 。这样在DLL中s这个全局变量是可以正常使用的,但s不能被调用程序使用,既s不能作为全局变量传递给调用程序。不过在调用程序中声明的变量可以作为参数传递给DLL。
二,动态调用
动态调用Dll文件要复杂很多,但非常灵活。在运行大的程序时可以节省内存空间。我们看下面的例子:
- procedure TForm1.btn1Click(Sender: TObject);
- type
- Taddc = function: TStringList; stdcall;
- var
- hh: THandle;
- addc: Taddc;
- temp: TStringList;
- i: Integer;
- begin
- hh := LoadLibrary('DLL.dll');
- try
- if hh <> 0 then
- @addc := GetProcAddress(hh, PChar('testStr'));
- if not (@addc = nil) then
- begin
- temp := addc;
- for i := 0 to temp.Count - 1 do
- showMessage(temp[i]);
- end
- else
- begin
- RaiseLastWin32Error;
- end;
- finally
- FreeLibrary(hh);
- end;
- end;
由上面代码可以看到,这种动态调用技术很复杂。但只要更改参数就可动态更改所调用Dll文件的名字。
1,在type中定义所要调用的函数或过程的类型,在这里同样也要加上stdcall参数。
2,释放Dll。在上面程序中我们使用LoadLibray函数加载了dll文件,在使用完Dll文件时切记调用FreeLibrary函数来释放Dll,否则Dll将会一直占用你的内存直至您退出Windows或是关机为止。在这里需要注意的是要确保在释放dll的时候没有任何指针指向该dll中所定义的变量、过程等,否则无法正常释放,招聘访问冲突异常。或是导致程序出现空指针,导致程序意外中止。
3,在动态调用的Dll函数中我们使用了string类型,由于在两处文件内都引用了ShareMem,所以string类型的数据可以正使用,以及作为参数来传递。
三,静态和动态调用的对比
1,静态方法实现简单,易于掌握。并且一般来说速度比较快,也更加安全可靠一些。但静态方法不能灵活地在运行时装卸所需的Dll,而主程序在开始运行时就装载了Dll只到程序结束时才释放该Dll。
2,动态方法很好地解决了静态方法中的不足,可以方便的访问Dll中的函数和过程。但动态方法难以完全掌握,使用时因为不同的函数或过程需要定义很多复杂的类型和调用方法。
[转]Delphi DLL的创建、静态 以及动态调用的更多相关文章
- Delphi DLL的创建、静态及动态调用
转载:http://blog.csdn.net/welcome000yy/article/details/7905463 结合这篇博客:http://www.cnblogs.com/xumenger/ ...
- RT-Thread创建静态、动态线程
RT-Thread 实时操作系统核心是一个高效的硬实时核心,它具备非常优异的实时性.稳定性.可剪裁性,当进行最小配置时,内核体积可以到 3k ROM 占用. 1k RAM 占用. RT-Thread ...
- Delphi DLL文件的静态调用
- delphi dll创建及调用
第一章 DLL简单介绍由于在目前的学习工作中,需要用到DLL文件,就学习了下,在这里作个总结.首先装简单介绍下DLL:1,减小可执行文件的大小DLL技术的产生有很大一部分原因是为了减小可执行文件的大小 ...
- Delphi 类库(DLL)动态调用与静态调用示例讲解
在Delphi或者其它程序中我们经常需要调用别人写好的DLL类库,下面直接上示例代码演示如何进行动态和静态的调用方法: { ************************************** ...
- C++调用DLL有两种方法——静态调用和动态调用
C++调用DLL有两种方法——静态调用和动态调用 标签: dllc++winapinullc 2011-09-09 09:49 11609人阅读 评论(0) 收藏 举报 分类: cpp(30) [ ...
- linux静态与动态库创建及使用实例
一,gcc基础语法: 基本语法结构:(由以下四部分组成) gcc -o 可执行文件名 依赖文件集(*.c/*.o) 依赖库文件及其头文件集(由-I或-L与-l指明) gcc 依赖文件集(*.c/*.o ...
- dll静态调用和动态调用
动态链接库有2种连接方式,一种是通过库直接加入(又叫隐式加载或载入时加载),一种是在运行时加入.后者很好理解,比如LoadLibrary(),GetProcAddress()获取想要引入的函数,使用完 ...
- Delphi动态调用C++写的DLL
c++ DLL 文件,建议用最简单的c++编辑工具.不会加入很多无关的DLL文件.本人用codeblocks+mingw.不像 VS2010,DLL编译成功,调用的时候会提示缺其他DLL. 系统生成的 ...
随机推荐
- CodeForces - 337D 树形dp
题意:一颗树上有且仅有一只恶魔,恶魔会污染距离它小于等于d的点,现在已经知道被污染的m个点,问恶魔在的可能结点的数量. 容易想到,要是一个点到(距离最远的两个点)的距离都小于等于d,那么这个点就有可能 ...
- python 对redis 键值对的操作
我们可以将Redis中的Hashes类型看成具有String Key和String Value的键值对容器.类似python中的dict,javascript的jaon,java 的map,每一个Ha ...
- poj 2752 kmp的next数组
题目大意: 求一个字符串中某一个既是前缀又是后缀的前缀的结尾下标: 基本思路: 从_next[len]开始找_next[_next[len]],再找_next[_next[_next[len]]],一 ...
- Java之JDBC操作数据库
DBC JDBC就是一套接口,真正执行的是jar包里得实现类,通过泛型对象来执行实现类里的方法. 步骤: ###1.导入驱动jar包到工程中 ###2.编写代码注册驱动,我们要让程序知道用的是哪个驱动 ...
- php重定向说明
302 临时重定向 header("location:http://api.com/headline?" . http_build_query($_REQUEST)); 301 ...
- 数组对象用map修改键名
用vue组件需要使用的数据格式和后台返回的不一样 console.log(res); this.optionsEp = res.map(item => { return { value: ite ...
- Unity NGUI插件
前言:关于Unity中关于UI的插件,我们最开始学的是UGUI,是Unity自带的UI系统,而在Unity版本还没更新出UGUI之前,除了NGUI没有一个更好些的插件,所以人们不得不去选择NGUI去制 ...
- sql 聚合查询
如果我们要统计一张表的数据量,例如,想查询students表一共有多少条记录,难道必须用SELECT * FROM students查出来然后再数一数有多少行吗? 这个方法当然可以,但是比较弱智.对于 ...
- mysql注入篇
博客这个东西真的很考验耐心,每写一篇笔记,都是在艰难的决定中施行的,毕竟谁都有懒惰的一面,就像这个,mysql注入篇,拖拖拖一直拖到现在才开始总结,因为这个实在是太多太杂了,细细的总结一篇太烧脑. 由 ...
- 一些基本LINUX命令以及测试环境的搭建
LINUX操作系统平时用的不多,资深测试与开发同学们用的比较多,像我这样的一个人,只喜欢WINDOWS操作系统.但LINUX操作系统也用过一段时间, 知道一些基本命令,如果不记得的话,就百度一下,拿来 ...