[转]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. 系统生成的 ...
随机推荐
- iptables 防火墙(下)
iptables 防火墙(下) 1. 常见的隐含匹配条件: 1.1 端口匹配: --sport 源端口.--dport 目的端口 1.2 TCP标记匹配: -tcp-flags 检查范围被设置的标记 ...
- ida x32 dbg 动态调试
http://www.xrwcn.com/html/8.html 0x20019u 注册表 RegOpenKeyEx函数 LONG RegOpenKeyEx( HKEY hKey, // handle ...
- pygame征途:(一)图片移动反弹
题目大意: 就是弄一张图片在背景画布上移动,然后碰到边界就图片翻转并且反向移动 基本思路: 需要pygame常用的一些常用的函数,然后基本就是在背景画布上blit一张图片,然后移动就是先全刷成背景画布 ...
- Mybatis调用Oracle中的存储过程和function
一.Mybatis调用存储过程 1 在数据库中创建以下的存储过程create or replace procedure pro_hello(p_user_name in varchar2,p_resu ...
- HTML标签分类总结
块级元素和行内元素块级元素address - 地址blockquote - 块引用center - 举中对齐块dir - 目录列表div - 常用块级容易,也是css layout的主要标签dl - ...
- Comet Contest#11 F arewell(DAG计数+FWT子集卷积)
传送门. 题解: 4月YY集训时做过DAG计数,和这个基本上是一样的,但是当时好像直接暴力子集卷积,不然我省选时不至于不会,这个就多了个边不选的概率和子集卷积. DAG计数是个套路来的,利用的是DAG ...
- java在acm中常用基础技巧方法
java在acm中常用基础技巧方法 如果学到了新的技巧,本博客会更新~ input input-std @Frosero import java.util.*; public class Main { ...
- BZOJ 4319: cerc2008 Suffix reconstruction(后缀数组)
题面 Description 话说练习后缀数组时,小C 刷遍 poj 后缀数组题, 各类字符串题闻之丧胆.就在准备对敌方武将发出连环杀时,对方一记无中生有,又一招顺 手牵羊,小C 程序中的原字符数组就 ...
- 关于Kerberos协议流程的总结
Kerberos协议工作原理分析 这里面借用一下师傅们的图来说明一下  Kerberos协议的流程大致如下(假设A要获取对Server B的访问权限) 第一步(KRB_AS_REQ) 这一步客户 ...
- XSS的原理分析与解剖:第四章(编码与绕过)*******************未看**********************
0×01前言 很抱歉,这第四章被我推了几个月,今天是元旦难得有空,就把第四章写下.我先把主要使用的编码说下,介绍完会说下绕过. 本文建议与<杂谈如何绕过WAF>一同阅读. 0×02 URL ...