MSVC 编译 DLL 不能调用问题 Q: 写一个 DLL ,使用 MinGW 编译,时,在动态加载,使用 GetProcAddress() 获取函数地址调用时,可成功调用。但是如果使用 MSVC 编译,DLL 可成功编译、加载,但,在 GetProcAddress() 获取函数地址,调用时,得到错误码 127 ,错误定义为,为找到相关函数。
A: MSVC 下有一个工具 dumpbin ,使用该工具可查看 DLL 的导出函数,在使用 MinGW 编译时,我们使用 dumpbin 查看DLL 的导出函数是这样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 > dumpbin -exports .\hello.dll Microsoft (R ) COFF/PE Dumper Version 14.29 .30141.0 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file .\hello.dll File Type : DLL Section contains the following exports for hello.dll 00000000 characteristics FFFFFFFF time date stamp 0.00 version 1 ordinal base 2 number of functions 2 number of names ordinal hint RVA name 1 0 00001000 _DllMain@12 2 1 00001040 show Summary 2000 .data 6000 .rdata 1000 .reloc C000 .text
使用 MSVC 编译时,函数导出表是这样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 > dumpbin -exports .\hellodll\Release\hello.dll Microsoft (R ) COFF/PE Dumper Version 14.29 .30141.0 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file .\hellodll\Release\hello.dll File Type : DLL Section contains the following exports for hellodll.dll 00000000 characteristics FFFFFFFF time date stamp 0.00 version 1 ordinal base 2 number of functions 2 number of names ordinal hint RVA name 1 0 00001030 ?show@ @YAXXZ 2 1 00001000 _DllMain@12 Summary 1000 .data 1000 .rdata 1000 .reloc 1000 .rsrc 1000 .text
看到,其中导出的函数名称发生了变化,在 c++ 中,编译器会按照自己的规则,更改函数名字,所以,在不同编译器的不同程序之间调用时,会调用失败。
R: 可在 export 函数前,使用 extern “C” ,使用内嵌 c 语言,不推荐此种方法。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #define WIN32_LEAN_AND_MEAN #include "pch.h" #include <windows.h> #pragma comment(lib, "user32.lib" ) extern "c" __declspec(dllexport)BOOL APIENTRY DllMain (HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: MessageBox (NULL , TEXT ("Hello world!" ), TEXT ("Hello World!" ), 0 ); break ; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break ; } return TRUE; } extern "c" __declspec(dllexport)void show () { MessageBox (NULL , TEXT ("xsxsxs" ), TEXT ("xsxsx" ), 0 ); }
使用 模块定义文件,代码中,可将函数 写成一般形式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #define WIN32_LEAN_AND_MEAN #include "pch.h" #include <windows.h> #pragma comment(lib, "user32.lib" ) BOOL APIENTRY DllMain (HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: MessageBox (NULL , TEXT ("Hello world!" ), TEXT ("Hello World!" ), 0 ); break ; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break ; } return TRUE; } void show () { MessageBox (NULL , TEXT ("xsxsxs" ), TEXT ("xsxsx" ), 0 ); }
新建一个 .def 后缀的文件,写入以下内容
1 2 3 4 LIBRARY hellodllEXPORTS show
在 vs studio 项目属性 / 连接器 / 模块定义文件 /
写入这个 .def 文件,重新编译,使用 dumpbin 查看函数导出表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 > dumpbin -exports .\hellodll\Release\hellodll.dll Microsoft (R ) COFF/PE Dumper Version 14.29 .30141.0 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file .\hellodll\Release\hellodll.dll File Type : DLL Section contains the following exports for hellodll.dll 00000000 characteristics FFFFFFFF time date stamp 0.00 version 1 ordinal base 2 number of functions 2 number of names ordinal hint RVA name 2 0 00001000 _DllMain@12 = _DllMain@12 1 1 00001030 show = ?show@ @YAXXZ (void __cdecl show(void)) Summary 1000 .data 1000 .rdata 1000 .reloc 1000 .rsrc 1000 .text
即可得到 正确地址调用
若使用命令编译
则可使用以下参数
cl .\dllmain.cpp /LD /link /DEF:hellodll.def 指定 def 文件,
Comments