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

来源:互联网 发布:魏晋风骨 知乎 编辑:程序博客网 时间:2024/06/05 00:13

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

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

函数的共享

在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’;

对象的共享

在c++与delphi之间的对象共享主要体现在对象方法(method)的共享方面,这种共享可分为两个层次:对象(object)级共享与类(class)级共享。

要实现对象级共享,程序设计语言需具备两个前提条件:
s 能够定义指向由另一语言创建的对象的指针;
s 可以访问由指针确定的对象中的方法。
要实现类级的共享,则还需考虑:
s 能够创建由另一种语言定义的类的实例;
s 可以从堆中释放一个实例所占用的空间;
s 派生新的类。

以下介绍在delphi与borland c++之间实现对象共享的方法。

1.c++共享delphi对象

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

要定义一个可供c++共享的delphi对象,共享接口的说明应注意s 在delphi程序里,要共享的方法必须被说明为抽象(abstract),而且虚拟(virtual );s 在c++程序里,必须用关键字"virtual"及"=0"后缀,把从delphi共享的方法说明成"pure virtual";s 共享的对象方法必须在两种语言里都被说明成相同的调用方式,通常使用标准系统调用方式(stdcall)。下面,举例说明这些规则,假设有这样的一个delphi对象:

ttestobject=class

procedure proc1(x:integer);
function func1(x:integer):pchar;
procedure proc2;
function func2:integer;
end;

如果c++程序需要共享其中的方法proc1、func1,可把上述说明修改成以下形式:

stestobject=class
procedure proc1(x:integer); virtual; abstract; stdcall;
function func1(x:integer); virtual; abstract; stdcall;
end;

ttestobject=class(stestobject)
procedure proc1(x:integer);
fuction func1(x:integer):pchar;
procedure proc2;
fuction func2:integer;
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 createtestobject:stestobject; 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(x:integer); virtual; abstract; stdcall;
function func1(x:integer); 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释放占用的空间。
0 0
原创粉丝点击