四 全局变量的使用
在widnows 32位程序中,两个应用程序的地址空间是相互没有联系的。虽然DLL在内存中是一份,但变量是在各进程的地址空间中,因此你不能借助dll的全局变量来达到两个应用程序间的数据传递,除非你用内存映像文件。
五 调用静态载入
1 客户端函数声名:
1)大小写敏感。
2)与DLL中的声明一样。如:Far;external'yproject_dll.dll';
3)调用时传过去的参数类型最好也与windows c++一样。
4)调用时DLL必须在windows搜索路径中,顺序是:当前目录;Path路径;windows;widows\system;windows\ssystem32;
六 调用动态载入
1 建立一种过程类型[如果你对过程类型的变量只是一个指针的本质清楚的话,你就知道是怎么回事了]。如:
type
mypointer=procedure(form:Tform);Far;external;
var
Hinst:Thandle;
begin
Hinst:=loadlibrary('yproject_dll');//Load一个Dll,按文件名找。
showform:=getprocaddress(Hinst,'showform');//按函数名找,大小写敏感。如果你知道自动化对象的本质就清楚了。
showform(application.mainform);//找到函数入口指针就调用。
Freelibrary(Hinst);
end;
例:
1.File->Close all->File->New﹝DLL﹞
代码: //自动产生Code如下
library Project2;
uses
SysUtils, Classes;
{$R *.RES}
begin
end.
2.加个Func进来:
代码:
library Project2;
uses
SysUtils, Classes;
Function stdcall ;
begin
if X > Y then Result := X
else Result := Y ;
end ;
//切记:Library 的名字大小写没关系,可是DLL-Func的大小写就有关系了。 在 DLL-Func-Name写成MyMax与myMAX是不同的。如果写错了,结果是此DLL的AP根本打不开。参数的大小写就没关系了。甚至不必同名。如原型中是 (X,Y:integer)但引用时写成(A,B:integer),那是没关系的。
//切记:要再加个stdcall。书上讲,如果你是用delphi写DLL,且希望不仅给delphi-AP也希望BCB/VC-AP等使用的话,那你最好加个Stdcall ; 的指示
//参数型态:delphi有很多种它自己的变量型态,这些当然不是DLL所喜欢的,Windows/DLL的母语是C。所以如果要传进传出DLL的参数,我们尽可能照规矩来用。
{$R *.RES}
begin
end.
3.将这些可共享的Func送出DLL,让外界﹝就是你的delphi-AP啦﹞使用:光如此,你的AP还不能用到这些,你还要加个Exports才行。
代码:
{$R *.RES}
exports
MyMax ;
begin
end.
4.好了,可以按 Ctrl-F9编译了。此时可不要按F9。DLL不是EXE不可单独执行的,如果你按F9,会有ErrorMsg的。这时如果DLL有Error,请修正之。再按Ctrl-F9。此时可能有Warning,不要紧,研究一下,看看就好。再按Ctrl-F9,此时就『Done , Compiled 』。同目录就会有个 *.dll 。恭喜,大功告成了。
1.加个TButton
代码: ShowMessage ( IntToStr(MyMax(30,50)) ) ;
2.告知Exe到那里抓个Func
代码: //在Form,interface,var后加
Function stdcall ; external 'MyTestDLL.dll' ;
// MyTestDLL.dll为你前时写的DLL项目名字
// DLL名字大小写没关系。不过记得要加 extension的 .DLL。在Win95或NT,是不必加 extension,但这两种OS,可能越来越少了吧。要加extension
在delphi 1或delphi 2环境下该调用参数是far。从delphi 3以后将这个参数变为了stdcall,目的是为了使用标准的Win32参数传递技术来代替优化的register参数。
1.在DLL中编写的函数或过程都必须加上stdcall调用参数。
2.所写的函数和过程应该用exports语句声明为外部函数。
3.当使用了长字符串类型的参数、变量时要引用ShareMem。
一、正如大家看到的,我们在external语句中指定了所要调用的DLL文件的名称。没有写路径是因为该DLL文件和调用它的主程序在同一目录下。如果该DLL文件在C:\,则我们可将上面的引用语句写为external ’C:\delphi.dll’。注意文件的后缀.dll必须写上。
二、不能从DLL中调用全局变量
如果我们在DLL中声明了某种全局变量,如:var s:byte 。这样在DLL中s这个全局变量是可以正常使用的,但s不能被调用程序使用,既s不能作为全局变量传递给调用程序。不过在调用程序中声明的变量可以作为参数传递给DLL。
三、被调用的DLL必须存在
这一点很重要,使用静态调用方法时要求所调用的DLL文件以及要调用的函数或过程等等必须存在。如果不存在或指定的路径和文件名不正确的话,运行主程序时系统会提示“启动程序时出错”或“找不到*.dll文件”等运行错误。
1 、我们知道DLL在编写时是不能运行和单步调试的。有一个办法可以,那就是在Run|parameters菜单中设置一个宿主程序。在Local页的Host Application栏中添上宿主程序的名字就可进行单步调试、断点观察和运行了。
2 、添加DLL的版本信息。开场白中提到了版本信息对于DLL是很重要的,如果包含了版本信息,DLL的大小会增加2Kb。增加这么一点空间是值得的。很不幸我们如果直接使用Project|options菜单中Version选项是不行的,这一点delphi的帮助文件中没有提到,经笔者研究发现,只要加一行代码就可以了。如下例:
library delphi;
uses
SysUtils, Classes;
{$R *.RES}
//注意,上面这行代码必须加在这个位置
functionstdcall;
begin Result:=i; end;
exports TestDll;
begin
end.
1 、在用静态方法时,可以给被调用的函数或过程更名。在前面提到的C++编写的DLL例子中,如果去掉extern ”C”语句,C++会编译出一些奇怪的函数名,原来的TestC函数会被命名为@TestC$s等等可笑的怪名字,这是由于C++采用了C++ name mangling技术。这个函数名在delphi中是非法的,我们可以这样解决这个问题:
,如何用Delphi编写dll文件