extern "c" 動態連接庫符號表導出問題 以及函數參數壓棧順序

c語言編譯的動態連接庫中,導出的符號名字就是 源代碼中的相應的名字;linux

例如函數 void test(){} 導出的符號名字 就是 testc++


可是對於c++ 來說不是這樣, c++ 有類, 名字空間, 函數重載, 致使多個不一樣的對象可能使用一個相同的名字, 這樣必須由編譯器來生成全局的惟一名字;
windows

這種生成的方式 沒有標準化, 因此 window上的vc 編譯器可能生成一種名字, linux上的gcc 可能生成一種名字, mingw 可能也會生成一種名字;函數

所以不一樣編譯器生成的C++動態庫, 從符號名字上來說,不兼容。指針


可是若是須要從C++庫導出某些名字 使得你們都認識該怎麼作呢?對象

源代碼中寫下:
編譯器

extern "c"{編譯

   void test();
test

}
import

將會生成 標準的c符號名字, 也就是 test, 這樣全部人都會認識這個符號了!

固然要注意一點 全部聲明該符號的位置 不能出如今名字空間中, 不然 仍舊生成 C++類型的符號名字。



標準c中定義了函數的參數的壓棧和出棧相關問題: 壓棧從右向左壓入參數;而當函數返回的時候, 由調用者負責清理堆棧, 彈出 相應的參數

也就是被調用者 直接return, 調用者再清理 堆棧頂部指針, 這樣實現printf 函數就比較方便了(可變長度參數, 被調用者不用關心參數的數量)


可是win32中, 有一種windows專用的stdcall方法, 參數也是從右向左壓入, 可是 函數返回的時候是由被調用者清理堆棧

也就是被調用者先拿到返回地址, 在設置堆棧頂部指針, 最後返回(被調用者須要關心參數的數量)



這些是windows 須要的東西:

所以在寫win32程序的時候 若是須要 採用標準的 c參數處理方式, 就須要顯示的告訴 編譯器;

__cdecl 標準c的參數管理方式                __stdcall windows的參數管理方式



主要用於dll說明參數的管理方式的:

__declspec(dllexport)用於導出 該動態庫 的標準c方式的函數

__declspec(dllimport) 用於一個動態庫 依賴於 另外一個動態庫的函數  

相關文章
相關標籤/搜索