如何调用用C++编写的Dll?(100分)

  • 主题发起人 主题发起人 HLAmy
  • 开始时间 开始时间
我有三个函数:
WORD FAR PASCAL AioInit (LPHANDLE, AINIT FAR *, AEXP FAR *);
WORD FAR PASCAL AioInp (HANDLE, AINP FAR *);
WORD FAR PASCAL AioEnd (HANDLE);
(在Aio.dll中)
想在Delphi中调用它们.但不知如何对它们进行说明.
 
Here is a sample for you.
You can modify the code following accordingly.
动态库之输入程式单元
(例-1):Delphi 之开发环境中之 uses windows
(例-2):
unit DateTime;{动态库之输入程式单元}
interface
type
TTimeRec = Record
ss : integer;
mi : Integer;
hh : Integer;
end;

type
TDateRec = Record
yy:Integer;
mm:Integer;
dd:Integer;
end;

Procedure SetTime(Var Time:TTimeRec);
Procedure GetTime(Var Time:TTimeRec);
Procedure SetDate(Var Date:TDateRec);
Procedure GetDate(Var Date:TDateRec);
Implementation
Procedure SetTime;
External 'DATETIME' index 1;
Procedure GetTime;
External 'DATETIME' index 2;
Procedure SetDate;
External 'DATETIME' index 3;
Procedure GetDate;
External 'DATETIME' index 4;
end;
------------------------------------------------------
program ShowTime;
{呼叫程式}
uses WinCrt , DateTime;
var
Time : TtimeRec;
begin
GetTime(Time);
With Timedo
WriteLn( 'Time is',hh,':',mi,':',ss);
end;
-----------------------------------------------------
 
有两种方法可用于调用一个储存在DLLs中的过程。  
1.静态调用或显示装载  
使用一个外部声明子句,使DLLs在应用程序开始执行前即被装入。例如:  
function Instr(SourceStr : PChar;Check : Char);
Integer;
far;
external '路径/文件名';
2.动态调用中的API函数
  (1)Loadlibrary: 把指定库模块装入内存
 function Loadlibrary(LibFileName: PChar): THandle;
(2)GetProcAddress:捡取给定模块中函数的地址
 function GetProcAddress(Module: THandle;
ProcName: PChar): TFarProc;
Module包含被调用的函数库模块的句柄,这个值由Loadlibrary返回。
如果把Module设置为nil,则表示要引用当前模块。  ProcName是指向含有函数名
的以nil结尾的字符串的指针,或者也可以是函数的次序值。如果ProcName参数是次序
值,则如果该次序值的函数在模块中并不存在时,GetProcAddress仍返回一个
非nil的值。这将引起混乱。因此大部分情况下用函数名是一种更好的选择。如果用函
数名,则函数名的拼写必须与动态链接库文件EXPORTS节中的对应拼写相一致。  
如果GetProcAddress执行成功,则返回模块中函数入口处的地址,否则返回nil。
(3)Freelibrary:从内存中移出库模块  
procedure Freelibrary(Module : THandle);

Module为库模块的句柄。这个值由Loadlibrary返回。  

Exmaple:
procedure TForm1.Edit2KeyPress(Sender: TObject;
var Key: Char);
var order: Integer;
txt: PChar;
PFunc: TFarProc;

Moudle: THandle;
begin

Moudle := Loadlibrary('c:/dlls/example.dll');

if Moudle > 32 then
begin
Edit2.text := '';
Pfunc := GetProcAddress(Moudle,'Instr');
txt := StrAlloc(80);
txt := StrPCopy(txt,Edit1.text);
Order := TInstr(PFunc)(txt,Key);
if Order = -1 then
Label1.Caption := '不包含这个字符 '
else
Label1.Caption := '位于第'+IntToStr(Order+1)+'位';
end;

Freelibrary(Moudle);
end;
  
在利用GetProcAddess返回的函数指针时,必须进行强制类型转换:
 
在Delphi中调用C++函数与C++调用Delphi函数相当直接,需要注意的是,
Delphi 1默认的函数调用方式是Pascal方式,Delphi 2、Delphi 3的
默认方式则是优化的cdecl调用方式,即register方式。要在C++与Delphi
程序之间实现函数共享,除非有充分的原因,否则应该使用标准系统调用方式,
即stdcall方式。为了使C++编译器不将函数标记为"mang led",使Delphi
编译器误认为函数是采用cdecl调用方式,应该在C++代码中,以extern "C "
说明被共享的函数,如下例所示:
原型说明:
在C++中:
extern "C" int _stdcall TestFunc();
在Delphi中:
function TestFunc:integer;
stdcall;
调用语法:
在C++中:
int i=TestFunc();
在Delphi中:
var i:integer;

begin

i:=TestFunc;

end;
共享函数的参数必须是两种语言都支持的变量类型,这是正确传递参数的前提。
诸如Delphi的currency、string、set等变量类型,在C++中没有相对应的
变量类型,不能被用作共享函数的参数。可以用PChar类型以值参的方式传递
字符串指针,这时用户必须注意字符串空间的回收。Delphi语言中的变参应被
说明成C++中相应变量类型的引用形式,如下:
在Delphi中:
function TestFunc(var i:integer):integer;
在C++中:
int TestFunc(int &i);
在Delphi与C++之间实现代码链接可采用静态链接或动态链接的方式。
1.静态链接方式
如果C++程序本身的代码量很小,而且无需担心与C运行库会有交互过程,
一般可选用静态链接方式,即把Delphi与C++的目标文件(*.OBJ)链接成
最终的可执行文件。具体的方法是使用{$L}编译指令,使Delphi编译器
自动读取指定目标文件,说明如下:
function TestFunc:integer;stdcall;
{$L TestFunc.OBJ}
2.动态链接方式
如果C++代码已经相当全面或自成一个完整的子系统,代码量很大,或者用到
了C运行库,在这种情况下,应该使用动态链接库(DLL)的方式。此时,在两种
语言的源代码中应做如下说明:
在C++中:
int stdcall export TestFunc();
在Delphi中:
function TestFunc:integer;
stdcall;
external ‘TestFunc.DLL’;
 
补充VB中的调用:
c++编译的test.dll 中有一函数是testfunction
在程序中声明为:
Private Declare Sub testfunction Lib "test.dll" (ByVal s1 As String)
调用:
testfunction("hello")
 
Implimentation部分(申明与定义结合):
WORD FAR PASCAL AioInit (LPHANDLE, AINIT FAR *, AEXP FAR *);
-->
function AioInit(Handle: Integer;
pointer1: PChar;
pointer2: PChar): word;
stdcall;
external 'Aio.dll' name 'AIOINIT';
WORD FAR PASCAL AioInp (HANDLE, AINP FAR *);
-->
function AioInp(handle: Integer;
Pointer: PChar): word;
stdcall;
external 'Aio.dll' name 'AIOINP';
WORD FAR PASCAL AioEnd (HANDLE);
-->
function AioEnd(Handle: Integer): word;
stdcall;
external 'Aio.dll' name 'AIOEND';
 
多人接受答案了。
 
后退
顶部