在Delphi與C++之間實現函式與物件共享 (轉)

worldblog發表於2007-12-03
在Delphi與C++之間實現函式與物件共享 (轉)[@more@]

 

以其獨特的面向的開發方式、強大的功能以及
的編譯技術,使得它自發布起即格外引人注意。隨著Delphi 3提
供豐富的Inte應用,Delphi日益成為最重要的開發工具之一,
它吸引了許多原、Foxpro、ase甚至C++的員,而
這些程式設計師使用Delphi時需要解決的一個重要問題就是怎樣利用他們
原有的程式碼。本文將介紹Delphi與C++程式整合的方法,包括:
S Delphi與C++之間的共享;
S 程式碼的靜態連結和動態連結;
S 的共享。
函式的共享
在Delphi中C++函式與C++呼叫Delphi函式相當直接,需要注
意的是,Delphi 1預設的函式呼叫方式是Pascal方式,Delphi 2、Delp
hi 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++中沒有相對應的變數型別,不能被用作共享函式的引數。可以用PC
har型別以值參的方式傳遞字串指標,這時必須注意字串空間
的回收。
Delphi語言中的變參應被說明成C++中相應變數型別的引用形式,
如下:
在Delphi中:
function TestFunc(var i:integer):integer;
在C++中:
int TestFunc(int &i);
程式碼連結
在Delphi與C++之間實現程式碼連結可採用靜態連結或動態連結的
方式。
1.靜態連結方式
如果C++程式本身的程式碼量很小,而且無需擔心與C執行庫會有交
互過程,一般可選用靜態連結方式,即把Delphi與C++的目標(*.OB
J)連結成最終的可檔案。具體的方法是使用{$L}編譯指令,使Del
phi編譯器自動讀取指定目標檔案,說明如下:
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)的
共享方面,這種共享可分為兩個層次:物件()級共享與類(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)"CreateTestOb
ject,該製造函式可被定義在動態連結庫或目標檔案(.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釋放佔用的空間。

浙江省奉化市房地產管理處 邵輝

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-987623/,如需轉載,請註明出處,否則將追究法律責任。

相關文章