__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)。
.def// dllTest.def
LIBRARY dllTest
EXPORTS
add
sub
// 可重命名:add1 = add
源碼無需導出聲明,鏈接時指定 .def。導出名為純函數名(無修飾),調用更簡單。
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 (被調用者)。
extern "C" __stdcall + .def,導出純函數名,跨語言調用友好__cdecldumpbin 是診斷導出名不匹配的利器
