一下仅列出主要代码,仅供参考。
Dll文件
CalculatorDll.dll
library CalculatorDll;
{ 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,
Unit1 in '..\计算器\Unit1.pas' {Form1};
function Add(x,y:double):double;stdcall;
begin
Result:=x+y;
end;
function Sub(x,y:double):double;stdcall;
begin
Result:=x-y;
end;
function Mul(x,y:double):double;stdcall;
begin
Result:=x*y;
end;
function Divide(x,y:double):double;stdcall;
begin
Result:=x/y;
end;
{$R *.res}
exports
Add,
Sub,
Mul,
Divide,
showForm
;
begin
end.
动态调用Dll文件
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, RzButton, StdCtrls, Mask, RzEdit;
type
TForm1 = class(TForm)
RzEdit1: TRzEdit;
RzEdit2: TRzEdit;
RzEdit3: TRzEdit;
ComboBox1: TComboBox;
RzBitBtn1: TRzBitBtn;
RzBitBtn2: TRzBitBtn;
Label1: TLabel;
Label2: TLabel;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure RzBitBtn2Click(Sender: TObject);
procedure RzBitBtn1Click(Sender: TObject);
// procedure DynamicLink(
private
{ Private declarations }
public
{ Public declarations }
end;
procedure showForm(app:Thandle);stdcall;
type
TAdd=function(x,y:double):double;stdcall;
TSub=function(x,y:double):double;stdcall;
TMul=function(x,y:double):double;stdcall;
TDivide=function(x,y:double):double;stdcall;
var
Form1: TForm1;
Bmp: TBitmap;
implementation
{$R *.dfm}
procedure showForm(app:Thandle);stdcall;
begin
try
app:=application.Handle;
form1:=Tform1.Create(application);
form1.ShowModal;
finally
freeAndNil(form1);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Bmp := TBitmap.Create;
Bmp.LoadFromFile('E:\54866b9d21fd6\cyd.bmp'); //背景图片
Brush.Bitmap:= Bmp;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Bmp.Free;
end;
procedure TForm1.RzBitBtn2Click(Sender: TObject);
begin
close;
end;
procedure TForm1.RzBitBtn1Click(Sender: TObject);
var FPointer:Pointer;
hDll:THandle;
vAdd:TAdd;
vSub:TSub;
vMul:TMul;
vDivide:TDivide;
a,b,r:double;
begin
a:=strtofloat(RzEdit1.Text);
b:=strtofloat(RzEdit2.Text);
//r:=strtoint(RzEdit3.Text);
case combobox1.ItemIndex of
0:
begin
hDll:=LoadLibrary(Pchar('D:\DelphiWorkSpace\DLL与计算器\CalculatorDll\CalculatorDll.dll'));
if hDll<=0 then
begin
showmessage('Dll文件找不到');
end
else
begin
if hDLL>0 then
begin
try
FPointer:=GetProcAddress(hDLL,PChar('Add'));
if FPointer <> nil then//如果函数存在就调用
begin
vAdd:=TAdd(FPointer);
RzEdit3.Text:=floattostr(vAdd(a,b));
end;
except
FreeLibrary(hDll);
end;
end;
end;
end;
1:
begin
hDll:=LoadLibrary(Pchar('D:\DelphiWorkSpace\DLL与计算器\CalculatorDll\CalculatorDll.dll'));
if hDll<=0 then
begin
showmessage('Dll文件找不到');
end
else
begin
if hDLL>0 then
begin
try
FPointer:=GetProcAddress(hDLL,PChar('Sub'));
if FPointer <> nil then//如果函数存在就调用
begin
vSub:=TSub(FPointer);
RzEdit3.Text:=floattostr(vSub(a,b));
end;
except
FreeLibrary(hDll);
end;
end;
end;
end;
2:
begin
hDll:=LoadLibrary(Pchar('D:\DelphiWorkSpace\DLL与计算器\CalculatorDll\CalculatorDll.dll'));
if hDll<=0 then
begin
showmessage('Dll文件找不到');
end
else
begin
if hDLL>0 then
begin
try
FPointer:=GetProcAddress(hDLL,PChar('Mul'));
if FPointer <> nil then//如果函数存在就调用
begin
vMul:=TMul(FPointer);
RzEdit3.Text:=floattostr(vMul(a,b));
end;
except
FreeLibrary(hDll);
end;
end;
end;
end;
3:
begin
hDll:=LoadLibrary(Pchar('D:\DelphiWorkSpace\DLL与计算器\CalculatorDll\CalculatorDll.dll'));
if hDll<=0 then
begin
showmessage('Dll文件找不到');
end
else
begin
if hDLL>0 then
begin
try
FPointer:=GetProcAddress(hDLL,PChar('Divide'));
if FPointer <> nil then//如果函数存在就调用
begin
vDivide:=TDivide(FPointer);
RzEdit3.Text:=floattostr(vDivide(a,b));
end;
except
FreeLibrary(hDll);
end;
end;
end;
end;
end;
end;
end.
静态调用方式:
优点:
静态调用方式简单。不占系统开销。
缺点:
在启动调用程序时即调入DLL作为备用过程,如果此DLL文件不存在,那么启动时即会提示错误并立刻终止程序。占内存空间。
调用方式:在宿主程序中进行声即可
譬如:function test(X:double;Y:double):integer;stdcall external 'TestDLL';
动态调用方式:
优点:
节约内存空间。而且可以判断装载是否正确,以避免调用程序崩溃的情况,最多损失该例程功能而已,不影响宿主程序其它部分。
缺点:
对于频繁使用的例程,因DLL的调入和释放会有额外的性能损耗,所以这样的例程则适合使用静态引入。
1. 第一步声明函数类型:
Type
TTest= function (X:double;Y:double):integer;stdcall;
2. 第二步
Var
Test:TTest; //创建一个函数对像
DllHandle: THandle; //定义一个句柄型的变量,用来存放DLL的文件句柄
3. 第三步
DllHandle:=LoadLibrary(PChar(DllName)); 获取DLL文件的句柄
4. 第四步 @Test= GetProcAddress(Module:THandle;ProcName:PChar);//返回一下要调用的DLL中的函数的地址
5. 第五步 判断获取函数地址是否成功
assigned 是用来判断某一指针(pointer)或过程引用是否为nil(空),如果为空则返回假(false)
if Assigned(@vTest) then
begin
第六步调用 vTest(I,J);
end;
6. 第七步 释放动态加载的DLL文件的
If hdll>0 then //如果调用DLL成功的话,那释放掉被调用的DLL
begin
FreeLibrary(hDLL);
end;
7.
可能会有人问到@,^是什么意思。
^: 指针 ,@: 取址
@:取址运算符;
var
int:integer;
p:^integer;
begin
new(P); //开辟一个新指针
int:=24; //给int 符值 24
p:=@int; /把 int变量的地址指针传给P
dispose(P);//释放
end;
符号 ^ 有两种用途,当它出现在类型标识符之前,如^typeName表示一个类型,该类型表示指向typeName类型变量的指针,当它出现在指针变量之后,如pointer^,该符号对指针解除参照,也就是说,返回存储在内存地址,该地址保存在指针中的值指针,指向的数据.
var
I:Integer;
PI:^Integer; //声明PI是一个Integer型的指针
begin
I:=10;
ShowMessage('I的内容:'+inttostr(i));
PI:=@I; //取 变量I的地址放到PI中去
PI^:=20; //PI中内存地址所指向内存空间 在这里PI^:=20 相当于 I:=20;
ShowMessage('I的内容:'+inttostr(i));
ShowMessage('PI^指向的内存单元内容:'+inttostr(PI^));
I:=PI^;
I:=I;
end;