extern "C" 和 DEF 文件.

参考:

http://www.cnblogs.com/whiteyun/archive/2011/07/22/2113560.html

 

问题: 如果用了 DEF 文件来导出 DLL 的函数, 还需要在导出的函数声明前面加 extern "C" 吗?

 

DEMO 下载: http://pan.baidu.com/s/1kTTY6rH

 

extern "C" 的目的是告诉 C++ 编译器不要对函数名进行改名处理(以便支持函数重载), 而是按照 C 编译器的方式, 不对函数名进行修改.

如果专门有头文件声明函数的话, extern "C" 以及 __declspec(dllexport) 只需要出现在头文件中即可, 定义函数的 .cpp 文件中可有可无.

如果没专门有头文件声明函数的话, extern "C" 以及 __declspec(dllexport) 必须出现在定义函数的 .cpp 文件中.

上述规则对纯 C 项目中的 __declspec(dllexport) 也适用.

做的实验, 思路如下, 即看各种配置下 Hello.h 中需不需要加 extern "C" 从而 UI2.EXE 可以通过 GetProcAddress("fnHello") 找到 Hello.dll 中的 fnHello:

注: Hello 项目中有一个 Hello.h

 1 UI2.EXE 编译为 C++ 项目 , HELLO.DLL 编译为 C++ 项目, C++ 编译器版本相同, Hello.h 中, 用 __declspec(dllexport) :
 2     Hello.h 有 extern "C", 成功, dumpbin /exports hello.dll 得到 _fnHello
 3     Hello.h 无 extern "C", 失败, dumpbin /exports hello.dll 得到 ?fnHello@@YAXXZ
 4 UI2.EXE 编译为 C++ 项目 , HELLO.DLL 编译为 C++ 项目, C++ 编译器版本相同, Hello.h 中, 无 __declspec(dllexport), 用 DEF 文件:
 5     Hello.h 有 extern "C", 成功, dumpbin /exports hello.dll 得到 _fnHello
 6     Hello.h 无 extern "C", 成功, dumpbin /exports hello.dll 得到 ?fnHello@@YAXXZ
 7 UI2.EXE 编译为 C++ 项目 , HELLO.DLL 编译为 C 项目, Hello.h 中, 用 __declspec(dllexport):
 8     Hello.h 有 extern "C", 成功, dumpbin /exports hello.dll 得到 _fnHello
 9     Hello.h 无 extern "C", 成功, dumpbin /exports hello.dll 得到 _fnHello
10 UI2.EXE 编译为 C++ 项目 , HELLO.DLL 编译为 C 项目, Hello.h 中, 无 __declspec(dllexport), 用 DEF 文件:
11     Hello.h 有 extern "C", 成功, dumpbin /exports hello.dll 得到 _fnHello
12     Hello.h 无 extern "C", 成功, dumpbin /exports hello.dll 得到 _fnHello
13 UI2.EXE 编译为 C 项目 , HELLO.DLL 编译为 C++ 项目, Hello.h 中, 用 __declspec(dllexport):
14     Hello.h 有 extern "C", 成功, dumpbin /exports hello.dll 得到 _fnHello
15     Hello.h 无 extern "C", 失败, dumpbin /exports hello.dll 得到 ?fnHello@@YAXXZ
16 UI2.EXE 编译为 C 项目 , HELLO.DLL 编译为 C++ 项目, Hello.h 中, 无 __declspec(dllexport), 用 DEF 文件:
17     Hello.h 有 extern "C", 成功, dumpbin /exports hello.dll 得到 _fnHello
18     Hello.h 无 extern "C", 成功, dumpbin /exports hello.dll 得到 ?fnHello@@YAXXZ

 

总结:
当 DLL 是 C++ 实现的时候,
用 DEF 文件, 无 extern "C", 此时 DLL 中导出的函数名仍然会被 C++ 编译器修改, 但仍然可用 GetProcAddress 找到函数.
用 __declspec(dllexport), 如果没有 extern "C", GetProcAddress 找不到函数.

当 DLL 是 C 实现的时候,
因为用的 C 编译器, 所以无论用 DEF 文件还是 __declspec(dllexport), 都不需要 extern "C", DLL 中导出的函数名始终不会被修改.
GetProcAddress 始终能找到函数.

posted @ 2016-01-05 10:47  rldts  阅读(527)  评论(0编辑  收藏  举报