1)使用vc6 编写动态库,动态库源码 (dll_test.cpp) 如下:
#include <windows.h> // _declspec(dllexport) means test() can be called by others void _declspec(dllexport) test() { MessageBox(NULL, "call test() success!", "test", MB_OK); } BOOL APIENTRY DllMain(HANDLE a, DWORD b, LPVOID c) { MessageBox(NULL, "in DllMain", "main", MB_OKCANCEL); return TRUE; }
生成动态库为 dll_test.dll,把它放到添加到系统可以找到的目录
在“运行中调用”
rundll32 dll_test.dll,test
有如下错误提示
使用 depends 分析原因
发现在 导出的函数名前后都有乱码,将其复制后,再次执行
rundll32 dll_test.dll,?test@@YAXXZ
2)修改源码,如下:
#include <windows.h> // _declspec(dllexport) means test() can be called by others extern "C" void _declspec(dllexport) test() { MessageBox(NULL, "call test() success!", "test", MB_OK); } BOOL APIENTRY DllMain(HANDLE a, DWORD b, LPVOID c) { MessageBox(NULL, "in DllMain", "main", MB_OKCANCEL); return TRUE; }
编译生成动态库后,通过 depends 查看:
同时使用 rundll32 dll_test.dll,test 进行测试,有正确结果如下:
3)原因分析
extern "C" 是告诉编译器用C语言的方式给函数命名。在用VC制作DLL导出函数时,由于C++存在函数重载,为了
实现同样的函数名可因参数不同而存在,所以在VC处理这些函数时,会把函数名编译成不同的名字以便自己识别。
例如:
int test(int, int) -> test@@YAHHH@Z
float test(float, float) -> test@@YAMMM@Z
但当我们使用 extern "C" 时,编译器会标识为: _函数名
int test(int, int) -> _test
float test(float, float) -> _test
因此被 extern "C" 修饰过的函数不再具备重载能力。