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 得到 [email protected]@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 得到 [email protected]@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 得到 [email protected]@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 得到 [email protected]@YAXXZ

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

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

时间: 2024-10-12 15:41:30

extern "C" 和 DEF 文件.的相关文章

VC2010 利用 def 文件生成 dll 文件的方法

近期有个需求,要生成一个dll 文件.文件里的函数都是採用 stdcall 函数调用约定,可是不希望函数名被修饰(add 被修饰成 [email protected]). 这时就要用def 文件了. 比方我有以下两个函数: extern "C" int _stdcall add(int a, int b) { return a + b; } extern "C" int _stdcall sub(int a, int b) { return a - b; } def

关于DLL的导出.def文件

1.VS2012创建.def文件 右键工程名->add->New Item->Visual C++->Code->Module-Define File(.def) 2.def文件的编写 一个def文件必须有两个部分:LIBRARY和EXPORTS 让我们先看一个基本的.def文件稍后我将解析 LIBRARY dll_tutorial DESCRIPTION "our simple DLL" EXPORTS Add @1 Function @2 第一行,''

VC2010 利用 def 文件生成 dll 文件的方法 转载

最近有个需求,要生成一个dll 文件,文件中的函数都是采用 stdcall 函数调用约定,但是不希望函数名被修饰(add 被修饰成 [email protected]).这时就要用def 文件了. 比如我有下面两个函数: [cpp] view plain copy extern "C" int  _stdcall add(int a, int b) { return a + b; } extern "C" int  _stdcall sub(int a, int b

由.def文件生成lib文件[转]

最近在学习curl库时,碰到一个问题,从官网上下载了一个lib版的,却发现只有.dll,没有lib文件,感觉很奇怪,google了之后才知道,原来库作者的用意是让用户自己生成lib文件,下载到的lib文件中含有.def文件.唉,用了vs有几个年头了,却连这么基础的问题都不知道,编译器是变得越来越智能了,只是让我们变得越来越傻了.下边我总结了一下由.def生成lib的方法. 在使用 VC 链接 dll 时,通常需要一个导入库文件(.lib),但有时我们只有一个 dll 文件,怎么办呢? 通常,在链

c++ exports def文件

https://msdn.microsoft.com/zh-cn/library/hyx1zcd3(v=vs.80).aspx EXPORTS 引入了一个由一个或多个 definitions(导出的函数或数据)组成的节.每个定义必须在单独一行上. EXPORTS definitions 备注 EXPORTS 关键字可以在第一个定义所在的同一行或前一行上..def 文件可以包含一个或多个 EXPORTS 语句. 导出 definitions 的语法为: entryname[=internalnam

VS制作dll、def文件的使用、dll加入工程使用

1.VS新建工程,在选项的时候,选择dll和空项目,保持干净的dll库: 创建完以后,添加头文件以及源文件. 2.将外部模块使用的接口导出: (1)函数导出: __declspec(dllexport) int add(int a, int b) { return a+b: } (2)类导出: class __declspec(dllexport) testClass() { testClass(); ~testClass(); } 3.直接buiild以后,在debug或者release的目录

DLL中__declspec(dllexport)和.def(模块定义文件)定义导出函数的一点区别

原想是不在DLL中使用.def文件的,直接在需要导出的函数前加__declspec(dllexport)修饰.但在是要导出STDAPI __declspec(dllexport) DllGetClassObject的时候,就提示"warning C4518: “__declspec(dllexport ) ” : 此处遇到意外的存储类或类型说明符:被忽略"(我用的是vc.net 2003). STDAPI这个宏扩展出来是extern "C" HRESULT __st

模块定义文件.def

一作用 DLL中导出函数的声明有两种方式:一种为在函数声明中加上__declspec(dllexport),这里不再举例说明:另外一种方式是采用模块定义(.def) 文件声明,.def文件为链接器提供了有关被链接程序的导出.属性及其他方面的信息. 在链接器阶段可以使用 /DEF(指定模块定义文件)链接器选项调用 .def 文件.如果生成的 .exe 文件没有导出,使用 .def 文件将使输出文件较大并降低加载速度. 二原因 在VC++中,生成DLL可以不使用.def文件.只需要在VC++的函数定

利用def生成dll文件

DLL中导出函数的声明有两种方式:一种为在函数声明中加上__declspec(dllexport),这里不再举例说明:另外一种方式是采用模块定义(.def) 文件声明,.def文件为链接器提供了有关被链接程序的导出.属性及其他方面的信息.            首先创建 一个DLL程序,.cpp中int __stdcall Add(int numa, int numb){       return (numa + numb);} int __stdcall Sub(int numa, int n