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

C++Builder 建立與使用 DLL 完整教學:靜態/動態連結、導出類與函數、記憶體管理陷阱

     編輯:VC 教學

一、建立 DLL 專案

  1. File → New → Other → DLL Wizard (或 Console Application 後改專案類型)。
  2. 專案產生 DllEntryPoint (進入點)、專案選項預設為動態 RTL、執行套件。**必須調整** (見第六節)。

二、導出函數 (C 風格,支援動態載入)

// Dll.h
#ifdef BUILDING_MYDLL
#define MYDLL_API extern "C" __declspec(dllexport)
#else
#define MYDLL_API extern "C" __declspec(dllimport)
#endif

MYDLL_API int __stdcall Add(int a, int b);
MYDLL_API void __stdcall GetVersion(char* buf, int bufSize);
// Dll.cpp
#include "Dll.h"
int __stdcall Add(int a, int b) { return a + b; }
void __stdcall GetVersion(char* buf, int bufSize) {
    const char* ver = "1.0.0";
    strncpy(buf, ver, bufSize-1);
    buf[bufSize-1] = '\0';
}

三、導出類 (僅靜態連結)

// DllClass.h
#ifdef BUILDING_MYDLL
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif

class DLLEXPORT __stdcall MyClass {
public:
    MyClass();
    ~MyClass();
    int Compute(int x);
private:
    int m_value;
};
// DllClass.cpp
#include "DllClass.h"
MyClass::MyClass() : m_value(42) {}
MyClass::~MyClass() {}
int MyClass::Compute(int x) { return m_value * x; }

四、靜態連結 (Load-time Dynamic Linking)

  1. 產生 Import Library:
    implib.exe MyDll.lib MyDll.dll (BCB 安裝目錄 Bin 下)。
  2. 專案 → Add to Project → 選擇 MyDll.lib。
  3. 引入標頭檔 #include "Dll.h" / #include "DllClass.h"。
  4. 直接呼叫函數、建立類物件:
// 使用導出函數
int result = Add(3, 5);

// 使用導出類
MyClass* obj = new MyClass();
int val = obj->Compute(10);
delete obj;  // 必須在 DLL 內部刪除,或共用記憶體管理器

五、動態連結 (Run-time Dynamic Linking)

typedef int (__stdcall *PFN_ADD)(int, int);
typedef void (__stdcall *PFN_GETVER)(char*, int);

HINSTANCE hDll = LoadLibrary("MyDll.dll");
if (hDll) {
    PFN_ADD pAdd = (PFN_ADD)GetProcAddress(hDll, "Add");
    PFN_GETVER pGetVer = (PFN_GETVER)GetProcAddress(hDll, "GetVersion");
    if (pAdd) { int r = pAdd(10, 20); }
    if (pGetVer) { char buf[64]; pGetVer(buf, sizeof(buf)); }
    FreeLibrary(hDll);
}
// 導出類動態載入極複雜 (需手動取得建構函數、虛函數表),
// 強烈建議改用「導出工廠函數回傳介面指標」模式 (COM 風格)。

六、專案設定關鍵 (避免部署地獄)

選項頁設定說明
Packages取消勾選 Build with runtime packages否則 DLL 依賴 vclxx.bpl, rtlxx.bpl 等巨大套件
Linker取消勾選 Use dynamic RTL否則 DLL 依賴 borlndmm.dll (記憶體管理器)
LinkerMap file = Detailed除錯時查看導出符號、段分佈

效果:產生獨立、無外部 VCL/RTL 依賴的 DLL,僅需系統 DLL (kernel32, user32 等)。體積較大但部署極簡單 (單檔)。

七、跨模組記憶體管理鐵律

  • 誰配置,誰釋放:DLL new 的記憶體,**必須由 DLL 內部 delete**。EXE 不得 delete DLL 配置的指標,反之亦然。
  • 違反會導致堆損壞、Crash、記憶體洩漏。
  • 解決方案:
    1. DLL 提供 CreateObject/DestroyObject 導出函數。
    2. 或啟用 Dynamic RTL 並部署 borlndmm.dll (共用記憶體管理器),但引入部署複雜度。
    3. 或使用 COM 介面 (IUnknown + AddRef/Release) 讓物件自我管理生命週期。

八、呼叫慣例統一

  • **全部導出函數/類成員函數使用 __stdcall** (Windows API 標準)。
  • BCB 預設 __cdecl,若混用會導致堆疊不平衡 Crash。
  • 類導出時在類前加 __stdcall:class __declspec(dllexport) __stdcall MyClass。

九、檢視導出符號

tdump -ee MyDll.dll        # BCB 工具
dumpbin /exports MyDll.dll # Visual Studio 工具

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved