[返回]
电脑报2000年第51期

在Delphi与C++之间实现函数和对象共享

北京 朱堂全

Delphi以其独特的面向控件的开发方式、强大的数据库功能和快速的编译技术使得它自发布起即格外引人注意。随着Delphi 3提供丰富的Internet应用Delphi日益成为最重要的软件开发工具之一 它甚至吸引了许多原C++的程序员而这些程序员使用Delphi时需要解决的一个重要问题就是怎样利用他们原有的代码。本文将介绍Delphi与C++程序集成的方法包括:Delphi与C++之间函数和对象的共享。

一、函数的共享

在Delphi中调用C++函数与C++中调用Delphi函数相当直接需要注意的是Delphi 1默认的函数调用方式是Pascal方式Delphi 2、Delphi 3的默认方式则是优化的cdecl调用方式即register方式。要在C++与Delphi程序之间实现函数共享除非有充分的原因否则应该使用标准系统调用方式即stdcall方式。为了使C++编译器不将函数标记为″mangled″使Delphi编译器误认为函数是采用cdecl调用方式应该在C++代码中以extern ″C″说明被共享的函数如下例所示

原型说明

在C++中
extern ″C″ int _stdcall TestFunc
在Delphi中
function TestFuncinteger stdcall
调用语法
在C++中
int i=TestFunc
在Delphi中
var iinteger
...
begin
...
i=TestFunc
...
end

共享函数的参数必须是两种语言都支持的变量类型这是正确传递参数的前提。诸如Delphi的currency、string、set等变量类型在C++中没有相对应的变量类型不能被用作共享函数的参数。可以用PChar类型以值参的方式传递字符串指针这时用户必须注意字符串空间的回收。

Delphi语言中的变参应被说明成C++中相应变量类型的引用形式如下:
在Delphi中:
function TestFuncvar iintegerinteger
在C++中
int TestFuncint &i


二、对象的共享

在C++与Delphi之间的对象共享主要体现在对象方法Method的共享方面这种共享可分为两个层次对象Object级共享与类Class级共享。
  (一) 要实现对象级共享程序设计语言需具备两个前提条件
  1.能够定义指向由另一语言创建的对象的指针。
  2.可以访问由指针确定的对象中的方法。
  3.要实现类级的共享则还需考虑
  ①能够创建由另一种语言定义的类的实例。
  ②可以从堆中释放一个实例所占用的空间。
  ③派生新的类。
  (二)在Delphi与Borland C++之间实现对象共享的方法:
  1.C++共享Delphi对象

要实现从C++调用Delphi对象首先要在Delphi单元的接口部分以及C++的头文件中说明需要共享的对象的接口在对象接口中定义该对象包含哪些属性与方法并说明可供共享的部分。对象的共享关键在于方法的共享。在Delphi语言中要使一个对象可以被共享可以把它说明为两个接口部分暂称为“共享接口”与“实现接口”。其中共享接口指明对象中哪些方法可被另一种语言所共享实现接口则继承共享接口并且在单元实现部分针对实现接口中的方法定义具体的实现。要定义一个可供C++共享的Delphi对象共享接口的说明应注意

在Delphi程序里要共享的方法必须被说明为抽象abstract而且虚拟virtual

在C++程序里必须用关键字″virtual″及″=0″后缀把从Delphi共享的方法说明成″pure virtual″

共享的对象方法必须在两种语言里都被说明成相同的调用方式通常使用标准系统调用方式stdcall。

下面举例说明这些规则假设有这样的一个Delphi对象


TTestObject=class
procedure Proc1xinteger
function Func1xintegerPChar
procedure Proc2
function Func2integer
end
如果C++程序需要共享其中的方法Proc1、Func1可把上述说明修改成以下形式
STestObject=class
procedure Proc1xinteger virtual abstract stdcall
function Func1xinteger virtual abstract stdcall
end
TTestObject=classSTestObject
procedure Proc1xinteger
fuction Func1xintegerPChar
procedure Proc2
fuction Func2integer
end
在C++程序中做如下对象原型说明
class STestObject 
virtual void Proc1int x=0
virtual char Func1int x=0

为了能在C++中成功地访问Delphi定义的类 Delphi接口说明时必须包含一个可共享的“制造函数Factory Function”CreateTestObject该制造函数可被定义在动态链接库或目标文件.OBJ中例如
Library TestLib
exports CreateTestObject
function CreateTestObjectSTestObject stdcall
begin
Result=TTestObject.Create
end
...
end.
经过这样的处理现在可在C++程序中使用这个由Delphi定义的对象调用方式如下
extern ″C″ STestObject stdcall CreateTestObject
void UseTestObjectvoid 
STestObject theTestObject=CreateTestObject
theTestObject->Proc110
Char str=theTestObject->Func10

当调用制造函数CreateTestObject时实际上已经在Delphi一侧占用了一个对象实例的空间C++程序在针对该对象的所有处理完成后必须考虑释放这一空间具体的实现可在Delphi中定义一个类如上述Proc1的共享方法Free以此来完成这一任务
STestObject=class
procedure Proc1xinteger virtual abstract stdcall
function Func1xinteger virtual abstract stdcall
procedure Free virtual abstract stdcall
end
...
implementation
...
procedure TTestObject.Free
begin
...
end
...
end.

2.Delphi共享C++对象

通常程序员会考虑使用Delphi来编制用户界面所以Delphi代码调用C++代码似乎显得更加实际些。其实Delphi共享C++对象的实现方法与上述C++共享Delphi对象非常相似。

用同样的共享接口与实现接口说明方法来定义C++的类
class STestObjedt 
virtual void Proc1int x=0
virtual char Func1int x=0

class TTestObjedt public STestObject 
void Proc1int x
char Func1int x
void Proc2
int Func2
void Free


然后实现这些方法。同样地C++对象需要一个与之对应的制造函数这里以DLL为例
STestObject stdcall export CreateTestObject 
return STestObject  new TTestObject.Create

Delphi代码可以通过调用制造函数CreateTestObject很容易地在C++中创建实例获得指向该实例的指针值并以这个指针值来调用对象中的共享方法。当然在进行完该对象的相关处理后千万不要忘了调用Free释放占用的空间。