Delphi以其独特的面向控件的开发方式
强大的数据库功能以及快速的编译技术
使得它自发布起即格外引人注意
随着Delphi
提供丰富的Internet应用
Delphi日益成为最重要的软件开发工具之一
它吸引了许多原Visual Basic
Foxpro
dBase甚至C++的程序员
而这些程序员使用Delphi时需要解决的一个重要问题就是怎样利用他们原有的代码
本文将介绍Delphi与C++程序集成的方法
包括:
Delphi与C++之间函数的共享;
代码的静态链接和动态链接;
对象的共享
函数的共享在Delphi中调用C++函数与C++调用Delphi函数相当直接需要注意的是Delphi 默认的
函数调用方式是Pascal方式Delphi Delphi 的默认方式则是优化的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的currencystringset等变量类型在C++中没有相对应的变量类型不能被用作共享函数的参数可以用PChar类型以值参的方式传递字符串指针这时用户必须注意字符串空间的回收
Delphi语言中的变参应被说明成C++中相应变量类型的引用形式如下:
在Delphi中:
function TestFunc(var i:integer):integer;
在C++中:
int TestFunc(int &i);
代码链接
在Delphi与C++之间实现代码链接可采用静态链接或动态链接的方式
静态链接方式
如果C++程序本身的代码量很小而且无需担心与C运行库会有交互过程一般可选用静态链接方式即把Delphi与C++的目标文件(*OBJ)链接成最终的可执行文件具体的方法是使用{$L}编译指令使Delphi编译器自动读取指定目标文件说明如下:
function TestFunc:integer;stdcall;
{$L TestFuncOBJ}
动态链接方式
如果C++代码已经相当全面或自成一个完整的子系统代码量很大或者用到了C运行库在这种情况下应该使用动态链接库(DLL)的方式此时在两种语言的源代码中应做如下说明:
在C++中:
int stdcall export TestFunc();
在Delphi中:
function TestFunc:integer; stdcall;
external TestFuncDLL;
对象的共享在C++与Delphi之间的对象共享主要体现在对象方法(Method)的共享方面这种共享可分为两个层次:对象(Object)级共享与类(Class)级共享要实现对象级共享程序设计语言需具备两个前提条件:
能够定义指向由另一语言创建的对象的指针;
可以访问由指针确定的对象中的方法
要实现类级的共享则还需考虑:
能够创建由另一种语言定义的类的实例;
可以从堆中释放一个实例所占用的空间;
派生新的类
以下介绍在Delphi与Borland C++之间实现对象共享的方法
C++共享Delphi对象
要实现从C++调用Delphi对象首先要在Delphi单元的接口部分以及C++的头文件中说明需要共享的对象的接口在对象接口中定义该对象包含哪些属性与方法并说明可供共享的部分对象的共享关键在于方法的共享在Delphi语言中要使一个对象可以被共享可以把它说明为两个接口部分暂称为共享接口与实现接口其中共享接口指明对象中哪些方法可被另一种语言所共享;实现接口则继承共享接口并且在单元实现部分针对实现接口中的方法定义具体的实现要定义一个可供C++共享的Delphi对象共享接口的说明应注意:
在Delphi程序里要共享的方法必须被说明为抽象(abstract)而且虚拟(virtual );
在C++程序里必须用关键字virtual及=后缀把从Delphi共享的方法说明成pure virtual;
共享的对象方法必须在两种语言里都被说明成相同的调用方式通常使用标准系统调用方式(stdcall)
下面举例说明这些规则假设有这样的一个Delphi对象:
TTestObject=class
procedure Proc(x:integer);
function Func(x:integer):PChar;
procedure Proc;
function Func:integer;
end;
如果C++程序需要共享其中的方法ProcFunc可把上述说明修改成以下形式:
STestObject=class
procedure Proc(x:integer); virtual; abstract; stdcall;
function Func(x:integer); virtual; abstract; stdcall;
end;
TTestObject=class(STestObject)
procedure Proc(x:integer);
fuction Func(x:integer):PChar;
procedure Proc;
fuction Func:integer;
end;
在C++程序中做如下对象原型说明:
class STestObject {
virtual void Proc(int x)=;
virtual char *Func(int x)=;
};
为了能在C++中成功地访问Delphi定义的类 Delphi接口说明时必须包含一个可共享的制造函数(Factory Function)CreateTestObject该制造函数可被定义在动态链接库或目标文件(OBJ)中例如:
Library TestLib;
exports CreateTestObject;
function CreateTestObject:STestObject; stdcall;
begin
Result:=TTestObjectCreate;
end;
…
end
经过这样的处理现在可在C++程序中使用这个由Delphi定义的对象调用方式如下:
extern C STestObject stdcall *CreateTestObject();
void UseTestObject(void) {
STestObject *theTestObject=CreateTestObject();
theTestObject>Proc();
Char *str=theTestObject>Func();
}
当调用制造函数CreateTestObject时实际上已经在Delphi一侧占用了一个对象实例的空间C++程序在针对该对象的所有处理完成后必须考虑释放这一空间具体的实现可在Delphi中定义一个类如上述Proc的共享方法Free以此来完成这一任务:
STestObject=class
procedure Proc(x:integer); virtual; abstract; stdcall;
function Func(x:integer); virtual; abstract; stdcall;
procedure Free; virtual; abstract; stdcall;
end;
…
implementation
…
procedure TTestObjectFree;
begin
…
end;
…
end
Delphi共享C++对象
通常程序员会考虑使用Delphi来编制用户界面所以Delphi代码调用C++代码似乎显得更加实际些其实Delphi共享C++对象的实现方法与上述C++共享Delphi对象非常相似用同样的共享接口与实现接口说明方法来定义C++的类:
class STestObjedt {
virtual void Proc(int x)=;
virtual char *Func(int x)=;
};
class TTestObjedt :public STestObject {
void Proc(int x);
char *Func(int x);
void Proc();
int Func();
void Free();
};
然后实现这些方法同样地C++对象需要一个与之对应的制造函数这里以DLL为例
STestObject stdcall export *CreateTestObject() {
return (STestObject *) new TTestObjectCreate;
}
Delphi代码可以通过调用制造函数CreateTestObject很容易地在C++中创建实例获得指向该实例的指针值并以这个指针值来调用对象中的共享方法当然在进行完该对象的相关处理后千万不要忘了调用Free释放占用的空间