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

C++Builder 動態連結庫鏈接問題:OMF/COFF 相容與解決方案

     編輯:VC 教學

C++Builder 使用 OMF 目標檔格式,而 Visual C++ 產出 COFF 格式。當嘗試在 C++Builder 專案中隱式連結 VC++ 產生的 DLL 導入庫(.lib)時,連結器會報錯 contains invalid OMF record。本文說明兩種解決路徑:顯式連結與 implib 工具轉換。

問題根源

  • VC++ 產生的 .lib 為 COFF 格式。
  • C++Builder 連結器只能處理 OMF 格式導入庫。
  • 直接加入 VC++ 的 .lib 會導致連結失敗。

方案一:顯式連結

不使用導入庫,改以 LoadLibrary/GetProcAddress 執行期載入:

// VC++ DLL 端:addit.h
extern "C" __declspec(dllexport) void addit(int a, int b, int* c);

// C++Builder 應用端
HINSTANCE hDll = LoadLibrary("addit.dll");
if (hDll) {
    typedef void (__cdecl *LPADDIT)(int, int, int*);
    LPADDIT pAddit = (LPADDIT)GetProcAddress(hDll, "addit");
    if (pAddit) {
        int result;
        pAddit(2, 3, &result); // 呼叫 DLL 函數
        // 使用 result...
    }
    FreeLibrary(hDll);
}

優點: 無相容性問題,執行期決定載入。
缺點: 程式碼較繁瑣,失去編譯期型別檢查,需手動管理 DLL 生命週期。

方案二:implib.exe 重新產生 OMF 導入庫

C++Builder 附贈 implib.exe 可從 DLL 直接產生 OMF 格式 .lib:

implib addit.lib addit.dll

然後修正標頭檔宣告,指定呼叫慣例(VC++ 預設 __cdecl,C++Builder 預設 __stdcall):

// addit.h 修正後
extern "C" void __stdcall addit(int a, int b, int* c); // 加上 __stdcall

最後在專案中加入產生的 addit.lib 與修正後的 addit.h,即可隱式連結。

呼叫慣例陷阱

編譯器預設呼叫慣例導出修飾
VC++ (cdecl)__cdecl_addit@12
C++Builder__stdcall_addit@12 (同名但堆疊清理不同)

若慣例不匹配,執行期會導致堆疊破壞。務必在標頭檔明確標註 __cdecl 或 __stdcall,並確雙方一致。

總結建議

  • 原始碼可控時:統一用 C++Builder 編譯 DLL,避免格式問題。
  • 僅有 VC++ DLL 二進位檔:優先用 implib + 慣例修正,保持隱式連結優雅。
  • 需延遲載入/條件載入:採顯式連結。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved