转自:http://blog.csdn.net/zhongjling/article/details/8088664

一般来讲,在DLL编程过程中,对于导出的函数前 都需要加入 extern “C”,

extern 表示这是个全局函数,可以供各个其他的函数调用;

“C” 表示编译时按照 C编译器的方式进行编译,而不是C++。 C++的编译方式考虑了函数重载,所以对函数名进行了新的修饰,产生了所谓的破坏性命名。

不过,也有特殊情况,有三种例外情况可以不加extern   “C”: 
1、如果不是用C++编译器而是用C编译DLL,名字不会变,可以不加extern   "C" 
2、如果DLL的使用者知道是用C++编译器编译DLL,不加extern   “C”也可以,因为他知道名字改变的规则。调用GetProcAddress时,把函数名字改了就是了,改为修饰后的函数名。 如 fnDll1  改为 ?fnDll1@@YAHXZ。

例子关键代码如下: 
---------------------------- 
DLL部分: 
//   This   is   an   example   of   an   exported   function. 
DLL1_API   int   __cdecl   fnDll1(void) 

return   42; 

输出的修饰函数名为?fnDll1@@YAHXZ 

DLL1_API   int   __cdecl   fnDll1(int   a) 

return   42+a; 

输出的修饰函数名为?fnDll1@@YAHH@Z 
----------------------------- 
EXE部分: 
HINSTANCE   hModule   =   LoadLibrary("dll1.dll"); 
ASSERT(hModule); 
typedef   int   (*fnDll1)(); 
fnDll1   pfnDll1   =   NULL; 
//VERIFY(pfnDll1   =   (fnDll1)::GetProcAddress(hModule,   "fnDll1")); 
VERIFY(pfnDll1   =   (fnDll1)::GetProcAddress(hModule,   "?fnDll1@@YAHXZ")); 
ASSERT(pfnDll1()   ==   42); 

typedef   int   (*fnDll2)(int); 
fnDll2   pfnDll2   =   NULL; 
VERIFY(pfnDll2   =   (fnDll2)::GetProcAddress(hModule,   "?fnDll1@@YAHH@Z")); 
ASSERT(pfnDll2(3)   ==   45); 
--------------------------- 

3.上面的2太麻烦了。所以还有一种方法是使用def文件。

 (如果DLL使用的是def文件,要删除TestDll.h文件中关键字extern "C",即2者是不能共存的)。

def 文件(模板定义文件),第一个语句必须是 LIBRARY 语句,指出DLL的名字;

EXPORTS语句 列出被导出函数的名字;将要输出的函数罗列出来,这个函数名字必须与定义函数的名字完全一致,如此既可以得到

一个没有任何修饰符的函数名了。

被导出的函数 可以和一个序号相对应。定义序号时必须在数字前加一个@。例如  isRUINIan  @1      //IsRuiNian 函数对应序号为 1

这样的话,我们既可以GetProAddress(hinstance,“IsRuiNian”),也可以 GetProAddress(hinstance,(LPCSTR)1)实现调用。

  

参考:http://topic.csdn.net/t/20021012/17/1090973.html

http://www.qqgb.com/program/vc/vcjq/program_166495.html

在DLL编程中,导出函数为什么需要extern "C"的更多相关文章

  1. DLL中导出函数的两种方式(dllexport与.def文件)

    DLL中导出函数的声明有两种方式: 一种方式是:在函数声明中加上__declspec(dllexport): 另外一种方式是:采用模块定义(.def)文件声明,(.def)文件为链接器提供了有关被链接 ...

  2. (转)DLL中导出函数的两种方式(dllexport与.def文件)

    DLL中导出函数的两种方式(dllexport与.def文件)http://www.cnblogs.com/enterBeijingThreetimes/archive/2010/08/04/1792 ...

  3. 【转】DLL中导出函数的两种方式(dllexport与.def文件)

    DLL中导出函数的两种方式(dllexport与.def文件) DLL中导出函数的声明有两种方式: 一种方式是:在函数声明中加上__declspec(dllexport):另外一种方式是:采用模块定义 ...

  4. VC 使用msxml6.dll动态链接库中的函数读写XML文件

    VC 使用msxml6.dll动态链接库中的函数读写XML文件 目录 1 引言 2 .dll使用方法 3 常用函数总结 4 实例应用 5 运行效果预览 6 补充说明 7 不足之处 8 更新   引言: ...

  5. 理解函数式编程中的函数组合--Monoids(二)

    使用函数式语言来建立领域模型--类型组合 理解函数式编程语言中的组合--前言(一) 理解函数式编程中的函数组合--Monoids(二) 继上篇文章引出<范畴论>之后,我准备通过几篇文章,来 ...

  6. Windows编程中回调函数的使用心得(MFC篇)

    回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调用,而是在特定 ...

  7. C++ DLL中导出函数的声明的方法

    定义: TESTDLLEXPORT_API int fnTestDllExport(void); TESTDLLEXPORT_API int fnTestCall(void); TESTDLLEXPO ...

  8. MFC DLL中导出函数模板

    //my.h struct AFX_EXT_CLASS B { }; struct AFX_EXT_CLASS C { }; class AFX_EXT_CLASS A { public: templ ...

  9. 【转】 嵌入式C语言编程中Inline函数的应用

    源地址:https://blog.csdn.net/vigour1000/article/details/9622037 有一段儿时间没写写经验笔记了,哎,也是自己这一段时间以来(其实最近一直是这个状 ...

随机推荐

  1. ios浅谈关于nil和 NIL区别及相关问题

    本文转载至:http://blog.csdn.net/guozh/article/details/8469131 1.nil和null从字面意思来理解比较简单,nil是一个对象,而NULL是一个值,我 ...

  2. 【BZOJ4318】OSU! 期望DP

    [BZOJ4318]OSU! Description osu 是一款群众喜闻乐见的休闲软件.  我们可以把osu的规则简化与改编成以下的样子:  一共有n次操作,每次操作只有成功与失败之分,成功对应1 ...

  3. 《从零开始学Swift》学习笔记(Day67)——Cocoa Touch设计模式及应用之MVC模式

    原创文章,欢迎转载.转载请注明:关东升的博客 MVC(Model-View-Controller,模型-视图-控制器)模式是相当古老的设计模式之一,它最早出现在Smalltalk语言中.现在,很多计算 ...

  4. js如何遍历并取出对象的属性名?

    js如何遍历并取出对象的属性名? dataObj = {name : su,age : 26,height : 18cm }; for(var st in dataObj) {console.dir( ...

  5. 后端程序员如何玩转AJAX

    1.原生的Ajax入门 (感觉很是繁琐,所以一般我们都是用简单的方式) 创建一个核心对象 XMLHttpRequest var xmlhttp; if (window.XMLHttpRequest) ...

  6. Python使用函数实现把字符串转换成整数

    需求:假设Python没有提供内置函数int如果使用函数方式实现把一串字符串转换成整数例如把字符串‘12345‘转换成整数12345 思路 1,字符串也是序列可以使用map函数处理分割成一个列表 2, ...

  7. Linux Shell 文本处理工具集锦--Awk―sed―cut(row-based, column-based),find、grep、xargs、sort、uniq、tr、cut、paste、wc

    本文将介绍Linux下使用Shell处理文本时最常用的工具:find.grep.xargs.sort.uniq.tr.cut.paste.wc.sed.awk:提供的例子和参数都是最常用和最为实用的: ...

  8. echarts将折线图改为曲线图

    只要在 series中加上属性: smooth: true(true为曲线.flase为直线)

  9. 解决Xshell中使用hbase shell backspace无法删除

    进入到XShell 文件 –> 属性 –> 终端 –> 键盘 在 DELETE键序列 和 BACKSPACE键序列 中都选择 ASCII 127 最后进入 Hbase 命令行测试,可 ...

  10. Error response from daemon: error creating overlay mount to /var/lib/docker/overlay2

    环境:centos7.1 docker run -t -i centos /bin/bash 运行上面的命令开启容器时报错: /usr/bin/docker-current: Error respon ...