1. windows下動態庫導出符號
根據C/C++語法規則,函數聲明中的修飾符(如__declspec(dllexport))可以放在返回類型之前或返回類型之后、函數名之前。這兩種方式在功能上是等價的,編譯器會以相同的方式處理。
__declspec(dllexport) int MyGlobalFunc(int a, int b);
int __declspec(dllexport) MyGlobalFunc(int a, int b);
注:
聲明函數/類的 簽名和導出屬性(如 extern “C” 或 __declspec(dllexport)),告知編譯器按特定規則生成符號名。編譯器在處理 CPP 文件時,會根據頭文件聲明自動應用導出規則,無需在實現中重復指定。
2. linux下動態庫導出符號
Linux 系統中導出動態庫(通常稱為共享對象 .so 文件)不需要使用 __declspec(dllexport)。這是 Linux 與 Windows 動態鏈接機制的核心區別,主要原因如下:
Linux下,動態庫符號默認全局可見性,Linux 的動態庫(.so)基于 ELF(Executable and Linkable Format)格式,默認導出所有全局函數和變量(除非顯式隱藏。無需額外聲明導出修飾符(如 Windows 的 __declspec(dllexport)),編譯器會直接導出符號。
linux下有個符號隱藏控制,可以控制符號的可見性,即使用 GCC 的編譯選項 -fvisibility=hidden,隱藏所有未顯式標記的符號。通過 attribute((visibility(“default”))) 顯式導出目標函數/類,例如:
// 顯式導出函數
__attribute__((visibility("default"))) void my_exported_func();
3. extern "C"修飾符
c++代碼使用,強制導出符號按c語言的規則,即不改寫函數名,一般有兩種寫法,
-
批量修飾
#ifdef __cplusplus extern "C" { #endif__declspec(dllexport) int MyGlobalFunc1(int a, int b);__declspec(dllexport) int MyGlobalFunc2(int a, int b);//略...#ifdef __cplusplus } #endif
-
單個修飾(簡化下,就省略了#ifdef __cplusplus,因為均是c++項目,上面是演示下如何使用宏去正確使用extern “C”)
extern "C" __declspec(dllexport) int MyGlobalFunc(int a, int b);
注:
聲明函數/類的 簽名和導出屬性(如 extern “C” 或 __declspec(dllexport)),告知編譯器按特定規則生成符號名。編譯器在處理 CPP 文件時,會根據頭文件聲明自動應用導出規則,無需在實現中重復指定。