許多初學者聽聞「C 語言不跨平台」,實則誤解。本文針對 Windows (VC++) ↔ Linux (GCC) 這對最主流的組合,實測驗證 C 原始碼級跨平台與二進制庫級互換的可行性路徑。
Java 靠 JRE 跨平台;C 靠 GCC 的跨平台實作。GCC 在 Linux 原生,移植到 Windows 有兩大環境:
cygwin1.dll,預設產出依賴該 DLL 的執行檔關鍵技巧:Cygwin 下加 -mno-cygwin 參數,同樣產出原生 PE(現代 MinGW-w64 已整合此功能)。
#include <stdio.h>
int main() { printf("hello world\n"); return 0; }
# MinGW
gcc -o hello hello.c
./hello # 正常
# Cygwin 預設
gcc -o hello hello.c
./hello # 正常
cmd /c hello.exe # 錯誤:找不到 cygwin1.dll
# Cygwin + -mno-cygwin
gcc -mno-cygwin -o hello hello.c
cmd /c hello.exe # 正常!

注意:
-mno-cygwin在某些複雜專案(如 Live555)下仍可能報錯,純 MinGW 環境相對穩定。
test/
├── lib/
│ ├── add.h
│ └── add.c
└── testlib/
└── test.c
// add.h
int add(int, int);
// add.c
#include "add.h"
int add(int x, int y) { return x + y; }
| 類型 | 指令 | 產物 |
|---|---|---|
| 靜態庫 | gcc -c add.c && ar crs libadd.a add.o | libadd.a |
| 動態庫 | gcc -shared -o libadd.dll add.c | libadd.dll |
# 連結靜態庫
gcc -o test test.c -I../lib -L../lib -ladd
./test # result=8
# 連結動態庫(刪除 .a 強制用 .dll)
rm ../lib/libadd.a
gcc -o test test.c -I../lib -L../lib -ladd
./test # 錯誤:找不到 libadd.dll
Linux 用 LD_LIBRARY_PATH,但 MinGW/Cygwin 只認 PATH:
export PATH=~/test/lib:${PATH}
./test # result=8 成功!
這正是 Windows 動態鏈接器的搜尋順序:應用目錄 → 系統目錄 →
PATH目錄。
| 方向 | 結果 | 條件/說明 |
|---|---|---|
| MinGW .dll → VC++ | ✅ 完全可用 | 標準 PE 格式,VC 直接 LoadLibrary/GetProcAddress 或連結 .lib |
| MinGW .a → VC++ | ✅ 可用 | 重命名 libadd.a → libadd.lib 即可連結 |
| VC++ .lib/.dll → MinGW | ⚠️ 僅 VC6 產物可用 | VC6 與 MinGW 同用 COFF 格式;VS2005+ 採用新格式,MinGW 無法識別 |

實戰意義:VLC 等開源專案的 MinGW 產出 DLL,可直接在 VC++ 專案中調用,無需重寫。
libvlc.dll 驗證完整鏈路本文出自 “海狗哥的流媒體空間” 博客,請務必保留此出處 https://jeremiah.blog.51cto.com/539865/183560