Delphi调用dll源码_delphi 调用dll

hacker|
120

文章目录:

delphi如何调用DLL

所谓的静态调用DLL是指程序加载的时候直接就把需要的DLL全部加载了,一直到程序运行结束才释放这些加载的DLL这个就是所谓的静态加载,动态加载就是需要一个DLL中某个函数的时候加载这个DLL运行完成了这个函数就释放DLL,这个就是动态加载!

你要静态加载DLL就用Delphi自己写一个DLL,并且写一个引出库(*.pas的),然后在你的应用程序中包含这个*.pas就根本不用声明DLL中那些乱七八糟的引出函数,直接用就可以了,如果该DLL不存在,那么整个应用程序将无法使用,但是动态调用DLL就不同了,就算DLL不在,应用程序仍然可以使用

访问DLL库有两种方式,一种是静态引用,另一种是动态引用。

用静态引用这种方法装入DLL要做两件事情:为DLL 库创建一个输入单元,以及用USES把输入单元连接到要使用DLL 函数的程序模块中。为DLL库创建的输入单元与普通的单元的区别仅在于:在它的接口处声明的过程、函数,并不在它的实现部分给出真正的实现代码,而是用external关键字把过程、函数的实现细节委托给外部DLL模块。

external命令的使用语法如下:

procedure /function 过程/函数名;external DLL模块名;

下面给出为上面创建的minmax.DLL库写的输入单元源文件testdll .pas,从中可看出输入单元 与一般 单元的一些差别,代码如下所示:

unit testdll;

interface

uses

function Min (X, Y: Integer): Integer;

function Max (X, Y: Integer): Integer;

implementation

function Min; external ‘minmax.DLL’;

function Max; external ‘minmax.DLL’;

end.

一个应用程序若想调用minmax.DLL中的函数,只须在其uses语句中加入testdll 单元即可。

动态装入DLL,要用到Windows的三个API函数。Loadlibrary、Freelibrary和GetprocAddress 。loadlibrary函数用来装入DLL库,其调用格式如下:

function loadlobrary (DLLfileName:Pchar): THandle:

当不再需要一个DLL库时,应调用FreeLibrary函数将其释放,以空出宝贵的内存资源,其调用格式如下:

procedure FreeLibrary (Libmodule:THandle)

Libmodule 为由LoadLibrary调用得到的DLL库句柄。在用loadlobrary 函数装入某个DLL库和调用FreeLibrary释放该DLL库之间的程序段中, 可以使用该DLL库中的过程和函数,

具体使用方法是:用GetprocAddress函数把DLL库中函数的地址传递给程序中某个函数变量,再用该变量实现DLL函数的调用。GetprocAddress函数声名如下,

function GetprocAddress (Libmodule:THandle:procname:pchar):TFarProc:

如下例所示:

type

TTimeRec = record

Second: Integer;

Minute: Integer;

Hour: Integer;

end;

TGetTime = procedure(var Time: TTimeRec);

THandle = Integer;

var

Time: TTimeRec;

Handle: THandle;

GetTime: TGetTime;

...

begin

Handle := LoadLibrary('DATETIME.DLL');

if Handle 0 then

begin

@GetTime := GetProcAddress(Handle, 'GetTime');

if @GetTime nil then

begin

GetTime(Time);

with Time do

WriteLn('The time is ', Hour, ':', Minute, ':', Second);

end;

FreeLibrary(Handle);

end;

end;

在调用动态链接库时应注意, 所需动态链接库须与应用程序在同一目录或Windows System 目录下。

静态调用

Function fun(para:Longint):Longint; stdcall; external 'xxx.dll';

动态调用

loadlibrary,getprocaddress,freelibrary三个函数

delphi 如何调用DLL文件,请详细写出代码,谢谢。 已知:TEST.dll 文件

function Get_tj_Driver( INT i_Item, HANDLE * ph_Drv ):Boolean;stdcall; external 'TEST.dll'

Get_tj_Driver( INT i_Item, HANDLE * ph_Drv ):为函数格式

Boolean:为函数返回类型--看你的函数返回值是什么类型这里就是什么类型。

怎样用DELPHI调用别的语言编写的DLL?

external ’Delphi.dll’;procedure TForm1.Button1Click(Sender: TObject);beginEdit1.Text:=IntToStr(TestDll(1)); end;end.上面的例子中我们在窗体上放置了一个编辑框(Edit)和一个按钮(Button),并且书写了很少的代码来测试我们刚刚编写的Delphi.dll。大家可以看到我们唯一做的工作是将TestDll函数的说明部分放在了implementation中,并且用external语句指定了Delphi.dll的位置。(本例中调用程序和Delphi.dll在同一个目录中。)让人兴奋的是,我们自己编写的TestDll函数很快被Delphi认出来了。您可做这样一个实验:输入“TestDll(”,很快Delphi就会用fly-by提示条提示您应该输入的参数是什么,就像我们使用Delphi中定义的其他函数一样简单。注意事项有以 下一些:一、调用参数用stdcall。 和前面提到的一样,当引用DLL中的函数和过程时也要使用stdcall参数,原因和前面提到的一样。二、用external语句指定被调用的DLL文件的路径和名称。 正如大家看到的,我们在external语句中指定了所要调用的DLL文件的名称。没有写路径是因为该DLL文件和调用它的主程序在同一目录下。如果该DLL文件在C:\,则我们可将上面的引用语句写为external ’C:\Delphi.dll’。注意文件的后缀.dll必须写上。三、不能从DLL中调用全局变量。 如果我们在DLL中声明了某种全局变量,如:var s:byte 。这样在DLL中s这个全局变量是可以正常使用的,但s不能被调用程序使用,既s不能作为全局变量传递给调用程序。不过在调用程序中声明的变量可以作为参数传递给DLL。四、被调用的DLL必须存在。 这一点很重要,使用静态调用方法时要求所调用的DLL文件以及要调用的函数或过程等等必须存在。如果不存在或指定的路径和文件名不正确的话,运行主程序时系统会提示“启动程序时出错”或“找不到*.dll文件”等运行错误。第四章 在Delphi中动态调用DLL top动态调用DLL相对复杂很多,但非常灵活。为了全面的说明该问题,这次我们举一个调用由C++编写的DLL的例子。首先在C++中编译下面的DLL源程序。#includeextern ”C” _declspec(dllexport) int WINAPI TestC(int i){return i;}编译后生成一个DLL文件,在这里我们称该文件为Cpp.dll,该DLL中只有一个返回整数类型的函数TestC。为了方便说明,我们仍然引用上面的调用程序,只是将原来的Button1Click过程中的语句用下面的代码替换掉了。procedure TForm1.Button1Click(Sender: TObject);typeTIntFunc=function(i:integer):integer;stdcall;varTh:Thandle; Tf:TIntFunc; Tp:TFarProc;beginTh:=LoadLibrary(’Cpp.dll’); {装载DLL} if Th0 thentryTp:=GetProcAddress(Th,PChar(’TestC’));if Tpnilthen beginTf:=TIntFunc(Tp); Edit1.Text:=IntToStr(Tf(1)); {调用TestC函数}endelseShowMessage(’TestC函数没有找到’);finallyFreeLibrary(Th); {释放DLL}endelseShowMessage(’Cpp.dll没有找到’); end;大家已经看到了,这种动态调用技术很复杂,但只要修改参数,如修改LoadLibrary(’Cpp.dll’)中的DLL名称为’Delphi.dll’就可动态更改所调用的DLL。一、定义所要调用的函数或过程的类型。 在上面的代码中我们定义了一个TIntFunc类型,这是对应我们将要调用的函数TestC的。在其他调用情况下也要做同样的定义工作。并且也要加上stdcall调用参数。二、释放所调用的DLL。 我们用LoadLibrary动态的调用了一个DLL,但要记住必须在使用完后手动地用FreeLibrary将该DLL释放掉,否则该DLL将一直占用内存直到您退出Windows或关机为止。现在我们来评价一下两种调用DLL的方法的优缺点。静态方法实现简单,易于掌握并且一般来说稍微快一点,也更加安全可靠一些;但是静态方法不能灵活地在运行时装卸所需的DLL,而是在主程序开始运行时就装载指定的DLL直到程序结束时才释放该DLL,另外只有基于编译器和链接器的系统(如Delphi)才可以使用该方法。动态方法较好地解决了静态方法中存在的不足,可以方便地访问DLL中的函数和过程,甚至一些老版本DLL中新添加的函数或过程;但动态方法难以完全掌握,使用时因为不同的函数或过程要定义很多很复杂的类型和调用方法。对于初学者,笔者建议您使用静态方法,待熟练后再使用动态调用方法。

请教在DELPHI中如何调用C语言的DLL文件

DELPHI可以调用任何语言写的DLL文件,调用的方法例子代码:

var

  psapi: cardinal;

  //下面申明DLL中子程序的原型

  EnumProcesses: function (lpidProcess, cb, cbNeeded: DWORD): Integer; stdcall;

  EnumProcessModules: function (hProcess: THandle; lphModule: HMODULE; cb, lpcbNeeded: DWORD): Integer; stdcall;

  GetModuleBaseNameA: function (hProcess: THandle; HMODULE: HMODULE; lpBaseName: PChar; nSize: DWORD): Integer; stdcall;

  GetModuleFileNameExA: function (hProcess: THandle; HMODULE: HMODULE; lpFileName: PChar; nSize: DWORD): Integer; stdcall;

begin

  //打开PSAPI.DLL文件

  psapi:=LoadLibrary('psapi');

  if psapi0 then

  try

    //把函数原型与DLL关联

    EnumProcesses:=GetProcAddress(psapi,'EnumProcesses');  

    EnumProcessModules:=GetProcAddress(psapi,'EnumProcessModules');

    GetModuleBaseNameA:=GetProcAddress(psapi,'GetModuleBaseNameA');

    GetModuleFileNameExA:=GetProcAddress(psapi,'GetModuleFileNameExA');

    //执行审核的函数

    if (@GetModuleBaseNameAnil) and (@GetModuleFileNameExAnil) and (@EnumProcessModulesnil) and (@EnumProcessesnil) then

用delphi编程,请问如何调用外来的dll文件,我是新手,越详细越好,谢谢了

Cdecl是函数调用协定的一种, 它规定了从C或C++编写的DLL中调用函数所必须遵守的规则.//它可以将C或C++中的数据类型转换为Delphi的

例如C++中的代码:

int X(int i)

{

return i*2;

}

这个函数被编译在Demo.dll中, 用Delphi调用时必须使用:function X(i: Integer): Integer; Cdecl; external'Demo.dll';

在Delphi里面如何使用DLL?

Delphi制作DLL

一 Dll的制作一般步骤

二 参数传递

三 DLL的初始化和退出清理[如果需要初始化和退出清理]

四 全局变量的使用

五 调用静态载入

六 调用动态载入

七 在DLL建立一个TForM

八 在DLL中建立一个TMDIChildForM

九 示例:

十 Delphi制作的Dll与其他语言的混合编程中常遇问题:

十一 相关资料

一 Dll的制作一般分为以下几步:

1 在一个DLL工程里写一个过程或函数

2 写一个Exports关键字,在其下写过程的名称。不用写参数和调用后缀。

二 参数传递

1 参数类型最好与window C++的参数类型一致。不要用DELPHI的数据类型。

2 最好有返回值[即使是一个过程],来报出调用成功或失败,或状态。成功或失败的返回值最好为1[成功]或0[失败].一句话,与windows c++兼容。

3 用stdcall声明后缀。

4 最好大小写敏感。

5 无须用far调用后缀,那只是为了与windows 16位程序兼容。

三 DLL的初始化和退出清理[如果需要初始化和退出清理]

1 DLLProc[SysUtils单元的一个Pointer]是DLL的入口。在此你可用你的函数替换了它的入口。但你的函数必须符合以下要求[其实就是一个回调函数]。如下:

procedure DllEnterPoint(dwReason: DWORD);far;stdcall;

dwReason参数有四种类型:

DLL_PROCESS_ATTACH:进程进入时

DLL_PROCESS_DETACH进程退出时

DLL_THREAD_ATTACH 线程进入时

DLL_THREAD_DETACH 线程退出时

在初始化部分写:

DLLProc := @DLLEnterPoint;

DllEnterPoint(DLL_PROCESS_ATTACH);

2 如Form上有TdcomConnection组件,就Uses Activex,在初始化时写一句CoInitialize (nil);

3 在退出时一定保证DcomConnection.Connected := False,并且数据集已关闭。否则报地址错。

四 全局变量的使用

在widnows 32位程序中,两个应用程序的地址空间是相互没有联系的。虽然DLL在内存中是一份,但变量是在各进程的地址空间中,因此你不能借助dll的全局变量来达到两个应用程序间的数据传递,除非你用内存映像文件。

五 调用静态载入

1 客户端函数声名:

1)大小写敏感。

2)与DLL中的声明一样。

如: showform(form:Tform);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;

showform:mypointer;

begin

Hinst:=loadlibrary('yproject_dll');//Load一个Dll,按文件名找。

showform:=getprocaddress(Hinst,'showform');//按函数名找,大小写敏感。如果你知道自动化对象的本质就清楚了。

showform(application.mainform);//找到函数入口指针就调用。

Freelibrary(Hinst);

end;

七 在DLL建立一个TForM

1 把你的Form Uses到Dll中,你的Form用到的关联的单元也要Uses进来[这是最麻烦的一点,因为你的Form或许Uses了许多特殊的单元或函数]

2 传递一个Application参数,用它建立Form.

八 在DLL中建立一个TMDIChildForM

1 Dll中的MDIForm.FormStyle不用为fmMDIChild.

2 在CreateForm后写以下两句:

function ShowForm(mainForm:TForm):integer;stdcall

var

Form1: TForm1;

ptr:PLongInt;

begin

ptr:=@(Application.MainForm);//先把dll的MainForm句柄保存起来,也无须释放,只不过是替换一下

ptr^:=LongInt(mainForm);//用主调程序的mainForm替换DLL的MainForm。MainForm是特殊的WINDOW,它专门管理Application中的Forms资源.

//为什么不直接Application.MainForm := mainForm,因为Application.MainForm是只读属性

Form1:=TForm1.Create(mainForm);//用参数建立

end;

备注:参数是主调程序的Application.MainForm

九 示例:

DLL源代码:

library Project2;

uses

SysUtils,

Classes,

Dialogs,

Forms,

Unit2 in 'Unit2.pas' {Form2};

{$R *.RES}

var

ccc: Pchar;

procedure OpenForm(mainForm:TForm);stdcall;

var

Form1: TForm1;

ptr:PLongInt;

begin

ptr:=@(Application.MainForm);

ptr^:=LongInt(mainForm);

Form1:=TForm1.Create(mainForm);

end;

procedure InputCCC(Text: Pchar);stdcall;

begin

ccc := Text;

end;

procedure ShowCCC;stdcall;

begin

ShowMessage(String(ccc));

end;

exports

OpenForm;

InputCCC,

ShowCCC;

begin

end.

调用方源代码:

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

StdCtrls;

type

TForm1 = class(TForm)

Button1: TButton;

Button2: TButton;

Edit1: TEdit;

procedure Button1Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.DFM}

procedure OpenForm(mainForm:TForm);stdcall;External'project2.dll';

procedure ShowCCC;stdcall;External'project2.dll';

procedure InputCCC(Text: Pchar);stdcall;External'project2.dll';

procedure TForm1.Button1Click(Sender: TObject);

var

Text: Pchar;

begin

Text := Pchar(Edit1.Text);

// OpenForm(Application.MainForm);//为了调MDICHILD

InputCCC(Text);//为了实验DLL中的全局变量是否在各个应用程序间共享

end;

procedure TForm1.Button2Click(Sender: TObject);

begin

ShowCCC;//这里表明WINDOWS 32位应用程序DLL中的全局变量也是在应用程序地址空间中,16位应用程序或许不同,没有做实验。

end;

3条大神的评论

  • avatar
    访客 2022-07-09 上午 02:59:19

    xternal'Demo.dll';在Delphi里面如何使用DLL?Delphi制作DLL一 Dll的制作一般步骤二 参数传递三 DLL的初始化和退出清理[如果需要初始化和退出清理]四 全局变量的使用五 调用静态载入六

  • avatar
    访客 2022-07-09 上午 08:53:25

    常遇问题:十一 相关资料一 Dll的制作一般分为以下几步:1 在一个DLL工程里写一个过程或函数2 写一个Exports关键字,在其下写过程的名称。不用写参数和调用后缀。二 参数传递1 参数类型

  • avatar
    访客 2022-07-09 上午 08:38:23

    数    if (@GetModuleBaseNameAnil) and (@GetModuleFileNameExAnil) and (@EnumProcessModulesnil) and (@Enum

发表评论