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

C++動態庫生成與調用全攻略:從隱式到顯式、從修飾名到.def

     編輯:關於C++

動態庫生成三種方式

1. __declspec(dllexport) 直接導出

// dllTest.cpp
__declspec(dllexport) int add(int a, int b) { return a+b; }
__declspec(dllexport) int sub(int a, int b) { return a-b; }

編譯生成 .dll、.lib、.exp。用 dumpbin -exports 查看導出名(C++ 修飾名如 ?add@@YAHHH@Z)。

2. 模塊定義文件 .def

// dllTest.def
LIBRARY dllTest
EXPORTS
    add
    sub
    // 可重命名:add1 = add

源碼無需導出聲明,鏈接時指定 .def。導出名為純函數名(無修飾),調用更簡單。

3. extern "C" + __stdcall (WINAPI)

// dllTest.h
#define DLLTEST_API extern "C" __declspec(dllimport/export)
DLLTEST_API int __stdcall add(int, int);

extern "C" 禁用 C++ 名稱修飾,__stdcall 由被調用者清理棧(Windows API 標準)。導出名如 _add@8(含參數字節數)。

調用方式對比

隱式鏈接(載入時綁定)

  • 配置工程:附加庫目錄 + 附加依賴項(或 #pragma comment(lib, "xxx.lib"))
  • 頭文件聲明:__declspec(dllimport) int add(int, int);
  • 直接調用,運行時需 .dll 在 PATH 或同目錄

顯式鏈接(運行時綁定)

HINSTANCE hInst = LoadLibraryA("dllTest.dll");
typedef int (*pFun)(int, int);
pFun add = (pFun)GetProcAddress(hInst, "add");  // 或修飾名/序號
add(5, 3);
FreeLibrary(hInst);
  • 無需 .lib、無需配置工程屬性
  • 按需加載,啟動更快
  • 需處理函數指針轉換與錯誤檢查

調用約定陷阱

_cdecl (默認):調用者清理棧,可變參數支援。
_stdcall:被調用者清理棧(ret n),固定參數,Windows API 標準。
混用後果:雙重清理棧導致返回地址/EBP 損壞,程序崩潰。匯編可見 add esp, 8 (調用者) vs ret 8 (被調用者)。

實戰建議

  1. 對外接口用 extern "C" __stdcall + .def,導出純函數名,跨語言調用友好
  2. 內部實現用默認 __cdecl
  3. 隱式鏈接簡單項目首選,插件架構用顯式鏈接
  4. dumpbin 是診斷導出名不匹配的利器

生成文件 VS命令提示 vcvarsall dumpbin導出 庫目錄配置 依賴項配置 運行結果 包含目錄配置 extern C導出名 stdcall導出名 def導出 def重命名導出 def+stdcall導出 調用者清理棧 被調用者清理棧 棧錯誤示意

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved