C++Builder 使用 OMF 目標檔格式,而 Visual C++ 產出 COFF 格式。當嘗試在 C++Builder 專案中隱式連結 VC++ 產生的 DLL 導入庫(.lib)時,連結器會報錯 contains invalid OMF record。本文說明兩種解決路徑:顯式連結與 implib 工具轉換。
.lib 為 COFF 格式。.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 生命週期。
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,並確雙方一致。
implib + 慣例修正,保持隱式連結優雅。