首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Delphi 與 C++ 互通:函數與物件共享完整指南

     編輯:關於C++

前言

Borland Delphi 與 C++ Builder 同屬 Embarcadero 工具鏈,共享 VCL 架構,理論上可無縫互通。但兩者函數呼叫慣例、名稱修飾、物件模型存在差異,需遵循特定規範才能實現函數共享與物件共享。本文系統整理靜態/動態連結、呼叫慣例、參數對應、物件介面定義與生命週期管理的完整實作規範。

一、函數共享核心規範

1. 統一呼叫慣例:stdcall

  • Delphi 1 預設 pascal,Delphi 4/5+ 預設 register
  • C++ 預設 cdecl
  • 必須雙方皆明確指定 stdcall(Win32 API 標準)

2. 防止 C++ 名稱修飾:extern "C"

  • C++ 編譯器會對函數名進行修飾(mangling)
  • 在 C++ 宣告加 extern "C" 保持原始符號名

3. 參數型別對應表

4. 宣告範例

// C++ 標頭檔
extern "C" int __stdcall AddNumbers(int a, int b);
extern "C" void __stdcall GetString(char* buffer, int maxLen);

// Delphi 單元
function AddNumbers(a, b: Integer): Integer; stdcall;
procedure GetString(buffer: PChar; maxLen: Integer); stdcall;

二、程式碼連結方式

1. 靜態連結(.obj)

  • 適用:C++ 程式碼量小、無 C 執行庫相依
  • Delphi 單元加入 {$L CppModule.obj} 指令
  • 連結階段將 .obj 合併至單一 EXE
// Delphi
function TestFunc: Integer; stdcall; {$L TestFunc.obj}

2. 動態連結(DLL)

  • 適用:C++ 程式碼龐大、使用 C RTL、獨立子系統
  • C++ 匯出:__declspec(dllexport) int __stdcall Func()
  • Delphi 匯入:function Func: Integer; stdcall; external 'MyDll.dll';
// C++ DLL
#define EXPORT_API __declspec(dllexport)
EXPORT_API int __stdcall AddNumbers(int a, int b) { return a+b; }

// Delphi
function AddNumbers(a, b: Integer): Integer; stdcall; external 'MathDll.dll';

三、物件共享:介面導向設計

核心原則:共享介面(純虛擬類別),隱藏實作細節。分為物件層級共享(既有實例)與類別層級共享(建立新實例、繼承)。

1. C++ 共享 Delphi 物件

步驟 1:定義共享介面(Delphi 側)

type
  // 共享介面:所有方法必須 virtual; abstract; stdcall
  ISharedObject = interface
    procedure Proc1(x: Integer); stdcall;
    function  Func1(x: Integer): PChar; stdcall;
    procedure Free; stdcall;  // 釋放自身
  end;

  // 實作類別:繼承共享介面
  TSharedObject = class(TInterfacedObject, ISharedObject)
    procedure Proc1(x: Integer); stdcall;
    function  Func1(x: Integer): PChar; stdcall;
    procedure Free; stdcall;
  end;

步驟 2:提供工廠函數(Delphi DLL 匯出)

function CreateSharedObject: ISharedObject; stdcall; export;
begin
  Result := TSharedObject.Create;
end;

exports CreateSharedObject;

步驟 3:C++ 端對應宣告與使用

// C++ 介面定義(純虛擬類別)
class ISharedObject {
public:
    virtual void __stdcall Proc1(int x) = 0;
    virtual char* __stdcall Func1(int x) = 0;
    virtual void __stdcall Free() = 0;
    virtual ~ISharedObject() {}
};

// 匯入工廠函數
extern "C" ISharedObject* __stdcall CreateSharedObject();

// 使用範例
void UseSharedObject() {
    ISharedObject* obj = CreateSharedObject();  // 取得介面指標
    obj->Proc1(10);
    char* str = obj->Func1(0);
    // ...
    obj->Free();  // 必須呼叫釋放,不可 delete
}

2. Delphi 共享 C++ 物件

步驟 1:C++ 定義共享介面與實作

// 共享介面
class ISharedObject {
public:
    virtual void __stdcall Proc1(int x) = 0;
    virtual char* __stdcall Func1(int x) = 0;
    virtual void __stdcall Free() = 0;
    virtual ~ISharedObject() {}
};

// 實作類別
class TSharedObject : public ISharedObject {
public:
    void __stdcall Proc1(int x) override { /* ... */ }
    char* __stdcall Func1(int x) override { return "Hello"; }
    void __stdcall Free() override { delete this; }  // 自刪
};

// 工廠函數匯出
extern "C" __declspec(dllexport) ISharedObject* __stdcall CreateSharedObject() {
    return new TSharedObject();
}

步驟 2:Delphi 端宣告與使用

type
  ISharedObject = interface
    procedure Proc1(x: Integer); stdcall;
    function  Func1(x: Integer): PChar; stdcall;
    procedure Free; stdcall;
  end;

function CreateSharedObject: ISharedObject; stdcall; external 'CppDll.dll';

procedure UseIt;
var
  Obj: ISharedObject;
begin
  Obj := CreateSharedObject;
  Obj.Proc1(10);
  ShowMessage(Obj.Func1(0));
  Obj.Free;  // 呼叫釋放
end;

四、關鍵注意事項總結

DelphiC++備註
Integerint / long32 位元有號
Booleanbool / BOOL
Char / AnsiCharchar
PCharchar* / const char*字串指標,注意記憶體歸屬
Doubledouble
Currency無直接對應避免作為共享參數
String不可直接共享改用 PChar + 長度參數
Set/Record不可直接共享改用結構體/位元遮罩
var 參數參考 (T&)輸出/輸入輸出參數
out 參數指標 (T*)純輸出參數
議題規範
呼叫慣例雙方強制 stdcall
C++ 名稱修飾共享函數/工廠函數加 extern "C"
共享介面方法全部 virtual + =0 (C++) / virtual; abstract (Delphi) + stdcall
字串傳遞使用 PChar / char*,明確約定緩衝區大小與記憶體釋放責任
物件生命週期提供 Free 方法由建立端釋放,嚴禁跨語言 delete/Free
例外處理介面方法不拋出例外,改用錯誤碼或 HRESULT 回傳
VCL 物件共享需在 DLL 中啟用 VCL,並注意 Application 物件同步

五、現代替代方案

  • COM/ActiveX:標準化二進位介面,支援跨語言、跨進程、參考計數
  • C++Builder 封裝為 BPL:執行階段套件,Delphi 可直接引用
  • REST/gRPC:跨進程、跨機器、跨語言的服務導向替代方案
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved