转自:https://blog.csdn.net/qing666888/article/details/41135245

一,__ declspec(dllexport):
将一个函数声名为导出函数,就是说这个函数要被其他程序调用,即作为DLL的一个对外函数接口。通常它和extern“C”合用,形式如下:

extern "C"
{__declspec(dllexport) void FUNCTION(){ }
} 

这是由于在制作DLL导出函数时由于C ++存在函数重载,因此__declspec(dllexport)FUNCTION(int,int)在DLL会被装饰,例如被装饰成为function_int_int,而且不同的编译器decorate的方法不同,造成了在用GetProcAddress的的取得FUNCTION地址时的不便,使用外部的“C”时,上述的装饰不会发生,因为ç没有函数重载,如此一来被外部的“C”修饰的函数,就不具备重载能力。

二,MSDN:
“在32位编译器版本中,可以使用__declspec(dllexport)关键字从DLL导出数据,函数,类或类成员函数.__ declspec(dllexport)将导出指令添加到对象文件(即obj文件) ,若要导出函数,__ declspec(dllexport)关键字必须出现在调用约定关键字的左边(如果指定了关键字)。例如:__ declspec
(dllexport)void __cdecl Function1(void);

若要导出类中的所有公共数据成员和成员函数,关键字必须出现在类名的左边,如下所示:
class __declspec(dllexport)CExampleExport:public CObject
{... class definition ...};

生成DLL时,通常创建一个包含正在导出的函数原型和/或类的头文件,并将__declspec(dllexport)的添加到头文件中的声明。
若要提高代码的可读性,请为__declspec(DLLEXPORT )定义一个宏并对正在导出的每个符号使用该宏:
#define DllExport __declspec(dllexport)“

三,__ declspec(dllexport)与.def
模块定义(.def)文件是包含一个或多个描述各种DLL属性的模块语句的文本文件
.1,二者的目的都是将公共符号导入到应用程序中或从DLL导出函数
.2,添加__declspec(dllexport)是为了提供不使用.def文件从.EXE或.DLL导出函数的简单方法
.3,如果不使用__declspec(dllimport)或__declspec(dllexport)导出DLL函数,则DLL需要.def文件
.4,并不是任何时候选择添加__declspec(dllexport)而放弃.def的方式都是好的。如果DLL是提供给VC ++用户使用的,只需要把编译DLL时产生的。 lib提供给用户,它可以很轻松地调用你的DLL。但是如果DLL是供VB,PB,Delphi用户使用的,那么会产生一个小麻烦。因为VC ++对于__declspec(dllexport)声明的函数会进行名称转换,如下面的函数:__ declspec 
     (dllexport)int __stdcall IsWinNT() 
     会转换为IsWinNT @ 0,这样你在VB中必须这样声明: 
     声明函数IsWinNT Lib“my.dll”别名“IsWinNT @ 0”()As Long 
     @的后面的数由于参数类型不同而可能不同。这显然不太方便。所以如果要想避免这种转换,就要使用.DEF文件方式。

在C ++中,我们可以通过  __declspec(DLLEXPORT)  将函数导出为DLL的中供其它程序使用,例如:

_declspec (dllexport )int add(int a,int b);

在这种方式下,如果调用该DLL的是一个C ++程序(同一个编译器的版本)是没有问题的。但是,如果调用该DLL是一个其它语言的程序(如C#,VB),则会出错。究其原因,是因为在C ++中存在函数的重载,允许函数重名,因此在编译器生成的DLL的时候,为了区别重名的程序,其会将进行一定算法进行名称转换。例如,对于前面的添加函数,实际的函数名称是如下形式。

因此,我们直接通过函数名add是无法找到该函数的,从而导致调用失败。为了解决这一问题,我们往往在函数前面再加一个extern “C”, 使用C方式的函数命名规则。

extern “C” _declspec (dllexport )int add(int a,int b);

这样函数的名称就成加了。

这样,我们就需要在每一个函数签名加上“ extern ”C“ _declspec (dllexport ) ” 这一长串声明。如果需要导出的函数较多则显得非常繁琐,也非常难看。为了简化这一过程, MS引入了高清文件网求方便我们操作。

使用默认值文件比较简单,只需要在项目中添加一个DEF文件,然后把我们要导出的函数放在DEF文件中即可。

DEF文件的简单示例如下:

    LIBRARY
    EXPORTS
        添加

最后记得在链接器选项中选中使用的DEF文件(默认情况下,添加DEF文件时会自动加上该选项,无需手动更改)。

这样,我们的函数无需加那一堆前缀,仍然可以使用默认的INT 添加(诠释一个,INT B);形式,导出但后的方式依然的英文Ç形式的函数定义。

最后指得一提的是,一般的C / C ++默认的调用方式是__cdecl,这种方式下需要调用方对函数清栈。如果对外提供API共其它非C ++程序使用时,调用方会无法清栈而出错(C#会直接报函数声明不匹配的错误)。因此,对外提供api时还应该将接口声明为__stdcall,让api函数自己清栈。这也是Windows API前面都加上了一个WINAPI的宏的原因。

def文件还有许多其它的高级用法,要进一步了解的话,可以参看一下MS的官方文档:http://msdn.microsoft.com/zh-cn/library/28d6s79h( v = vs.80).aspx

【转】extern “C“以及__declspec(dllexport) 讲解和def文件dll导出方法相关推荐

  1. 【转】extern “C“和__declspec(dllexport)以及__declspec(dllimport) 和def的简单解析

    转自:https://blog.csdn.net/xupan_jsj/article/details/9028759 前面的extern "C"  __declspec(dllex ...

  2. extern C和__declspec(dllexport)以及__declspec(dllimport) 和def的简单解析

    前面的extern "C"  __declspec(dllexport)  __declspec(dllimport)都是用于函数或者变量,甚至类的声明的(可以把extern &q ...

  3. 使用def文件从dll导出和_declspec(dllexport)导出区别以及调用示例

    在C++中,我们可以通过 __declspec(dllexport) 将函数导出为Dll中供其它程序使用,例如: _declspec(dllexport) int add(int a, int b); ...

  4. extern C __declspec(dllexport)

    一.__declspec(dllexport): 将一个函数声名为导出函数,就是说这个函数要被其他程序调用,即作为DLL的一个对外函数接口. 通常它和extern    "C"   ...

  5. Windows DLL编程中的导入导出:__declspec(dllimport) ,__declspec(dllexport) ,

    在Windows DLL编程时,可使用__declspec(dllimport)关键字导入函数或者变量. 函数的导入 当你需要使用DLL中的函数时,往往不需要显示地导入函数,编译器可自动完成.但如果你 ...

  6. extern C __declspec(dllexport) __declspec(dllimport) 和 def

    前面的extern "C"  __declspec(dllexport)  __declspec(dllimport)都是用于函数或者变量,甚至类的声明的(可以把extern &q ...

  7. Windows C++中__declspec(dllexport)的使用

    __declspec是Microsoft VC中专用的关键字,它配合着一些属性可以对标准C/C++进行扩充.__declspec关键字应该出现在声明的前面. __declspec(dllexport) ...

  8. C++dll导出类的方式__declspec(dllexport)

    前言 有时导出dll的时候既想用到整个类又想保持多态 一.直接导出整个类 示例: 头文件 #ifdef AITWapper_EXP //根据项目是导入导出预定义 #define AITWapper_D ...

  9. OpenCV中# define CV_EXPORTS __declspec(dllexport)的含义

    # define CV_EXPORTS __declspec(dllexport) 问题出自: class CV_EXPORTS Mat { ................... }; __decl ...

最新文章

  1. 公式没有编号_知乎公式编辑器的一些小技巧 amp; 使用规范
  2. 最先进的NAS算法不如随机搜索,瑞士学者研究结果让人吃惊,也令人怀疑
  3. c++ socket error 10038错误
  4. 「模拟赛20180307」三元组 exclaim 枚举+树状数组
  5. DEDECMS模块插件制作举例-模块生成向导
  6. sublime写网页代码,里面的中文字符会出现乱码
  7. 《Scikit-Learn与TensorFlow机器学习实用指南》第16章 强化学习
  8. 梯度消失和梯度爆炸_梯度消失和梯度爆炸详解
  9. CSocket实现端口扫描
  10. 自存:微软应用商店appx下载
  11. android购物车计数器,Axure教程:计数器的实战应用场景 —— 商品购件数
  12. AD统一查看元器件得封装信息
  13. 如何在Word中绘制流程图
  14. 史上最全的oracle常用知识总结
  15. Android CameraX 使用入门
  16. windows无法访问指定设备路径或文件
  17. 《MATLAB金融算法分析实战》之量化投资趋向指标1— python实现
  18. vmvare打开虚拟机时报错:vmx文件已损坏
  19. 旗鼓相当的对手——加强版
  20. ezdml 支付mysql 吗_关于EZDML数据库表结构制作设计工具使用踩的坑

热门文章

  1. Java 中的 Reference
  2. JDBC_设计架构_驱动类加载_建立Connection_效率测试
  3. 上传文件Base64格式(React)
  4. Java读源代码学设计模式:适配器Adapter
  5. MySQL中order by中关于NULL值的排序问题
  6. 数据库方面的操作示例
  7. [Leetcode][第410题][JAVA][分割数组的最大值][动态规划][二分]
  8. pat-1136. A Delayed Palindrome (20) 模拟
  9. python3纵向输出字符串_Python 3.x 格式化输出字符串 % format 笔记
  10. python微信推送消息_Python编程之微信推送模板消息功能示例