【转载】 __declspec(dllexport) 和__declspec(dllimport)
转自:http://www.cppblog.com/Dutyboy/archive/2010/11/15/133699.html
__declspec(dllexport)
__declspec(dllexport) 将一个函数声名为导出函数,就是说这个函数要被包含她的程序之外的程序调用。
extern "C" 指示编译器用C语言方法给函数命名。
在制作DLL导出函数时由于C++存在函数重载,因此__declspec(dllexport) function(int,int) 在DLL会被decorate,例如被decorate成为 function_int_int,而且不同的编译器decorate的方法不同,造成了在用GetProcAddress取得function地址时的不便,使用extern "C"时,上述的decorate不会发生,因为C没有函数重载,但如此一来被extern"C"修饰的函数,就不具备重载能力,可以说extern 和 extern "C"不是一回事。
__declspec(dllimport)
我相信写WIN32程序的人,做过DLL,都会很清楚__declspec(dllexport)的作用,它就是为了省掉在DEF文件中手工定义导出哪些函数的一个方法。当然,如果你的DLL里全是C++的类的话,你无法在DEF里指定导出的函数,只能用__declspec(dllexport)导出类。但是,MSDN文档里面,对于__declspec(dllimport)的说明让人感觉有点奇怪,先来看看MSDN里面是怎么说的:
不使用 __declspec(dllimport) 也能正确编译代码,但使用 __declspec(dllimport) 使编译器可以生成更好的代码。编译器之所以能够生成更好的代码,是因为它可以确定函数是否存在于 DLL 中,这使得编译器可以生成跳过间接寻址级别的代码,而这些代码通常会出现在跨 DLL 边界的函数调用中。但是,必须使用 __declspec(dllimport) 才能导入 DLL 中使用的变量。
初看起来,这段话前面的意思是,不用它也可以正常使用DLL的导出库,但最后一句话又说,必须使用 __declspec(dllimport) 才能导入 DLL 中使用的变量这个是什么意思??
那我就来试验一下,假定,你在DLL里只导出一个简单的类,注意,我假定你已经在项目属性中定义了 SIMPLEDLL_EXPORT
SimpleDLLClass.h
#ifdef SIMPLEDLL_EXPORT
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT
#endif
class DLL_EXPORT SimpleDLLClass
{
public:
SimpleDLLClass();
virtual ~SimpleDLLClass();
virtual getValue() { return m_nValue;};
private:
int m_nValue;
};
SimpleDLLClass.cpp
#include "SimpleDLLClass.h"
SimpleDLLClass::SimpleDLLClass()
{
m_nValue=0;
}
SimpleDLLClass::~SimpleDLLClass()
{
}
然后你再使用这个DLL类,在你的APP中include SimpleDLLClass.h时,你的APP的项目不用定义 SIMPLEDLL_EXPORT 所以,DLL_EXPORT 就不会存在了,这个时候,你在APP中,不会遇到问题。这正好对应MSDN上说的__declspec(dllimport)定义与否都可以正常使用。但我们也没有遇到变量不能正常使用呀。 那好,我们改一下SimpleDLLClass,把它的m_nValue改成static,然后在cpp文件中加一行
int SimpleDLLClass::m_nValue=0;
如果你不知道为什么要加这一行,那就回去看看C++的基础。 改完之后,再去LINK一下,你的APP,看结果如何, 结果是LINK告诉你找不到这个m_nValue。明明已经定义了,为什么又没有了?? 肯定是因为我把m_nValue定义为static的原因。但如果我一定要使用Singleton的Design Pattern的话,那这个类肯定是要有一个静态成员,每次LINK都没有,那不是完了? 如果你有Platform SDK,用里面的Depend程序看一下,DLL中又的确是有这个m_nValue导出的呀。
再回去看看我引用MSDN的那段话的最后一句。 那我们再改一下SimpleDLLClass.h,把那段改成下面的样子:
#ifdef SIMPLEDLL_EXPORT
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
再LINK,一切正常。原来dllimport是为了更好的处理类中的静态成员变量的,如果没有静态成员变量,那么这个__declspec(dllimport)无所谓。
【转载】 __declspec(dllexport) 和__declspec(dllimport)的更多相关文章
- __declspec(dllexport) 和 __declspec(dllimport)的区别
最近看MXNet的源码,其中c_api.h中发现遇到__declspec(dllexport) 和 __declspec(dllimport). __declspec(dllexport)用于导出符号 ...
- __declspec(dllexport)和__declspec(dllimport) (——declspec方法创建dll的方法已验证ok)
转载:https://www.cnblogs.com/chengbing2011/p/4084125.html __declspec(dllimport)和__declspec(dllexport)经 ...
- 浅谈__declspec(dllexport)和__declspec(dllimport)
__declspec(dllimport)和__declspec(dllexport)经常是成对的,在动态链接库中__declspec(dllexport)导出dll中的成员,__declspec(d ...
- 理解 __declspec(dllexport)和__declspec(dllimport)
1.解决的问题: 考虑下面的需求,使用一个方法,一个是提供者,一个是使用者,二者之间的接口是头文件.头文件中声明了方法,在提供者那里方法应该被声明为__declspec(dllexport),在使用者 ...
- __declspec(dllexport) 和 __declspec(dllimport)的作用
operatordll.h #include <iostream> #ifndef _WIN32 #define DLL_EXPORT#else #ifdef OPERATORDLL_EX ...
- 通过宏定义将__declspec(dllexport)与__declspec(dllimport)的转化,实现库代码和使用代码使用同一份头文件
我们知道,在VC编程中,如果要编译成动态链接库,需要将函数.变量.类等导出,这时使用__declspec(dllexport).使用动态链接库时,需要在声明的时候有使用__declspec(dllim ...
- __declspec(dllexport)
__declspec(dllexport) (2010-06-17 10:04:28) 转载▼ 标签: __declspec dllexport 导出 it 分类: C 先看代码:以下是在dev-c+ ...
- 【转载】extern "C" __declspec(dllexport) __declspec(dllimport) 和 def
转自:http://www.cppblog.com/FateNo13/archive/2009/08/03/92052.html 前面的extern "C" __declspec ...
- extern "C" __declspec(dllexport) __declspec(dllimport) 和 def
原文:extern "C" __declspec(dllexport) __declspec(dllimport) 和 def 前面的extern "C" _ ...
随机推荐
- 战“疫”背后的AI身影丨曼孚科技
近期新型冠状病毒肺炎的疫情,牵动着全国上下人民的心. 截止2月11日上午10点,全国确诊人数已达42708人,疑似病例21675人. 突发的疫情让部分地区的快速诊疗能力出现了结构性的缺失,为了打赢这场 ...
- 给你的HTTPS添加Let's Encrypt证书
Let’s Encrypt setup for Apache, NGINX & Node.js https://gist.github.com/davestevens/c9e437afbb41 ...
- 在javascript编程语言中,数据类型boolean的相关知识
一. 1.字符串类型: 空字符串返回false,非空字符串均返回true; 2.数值类型: 0或NaN返回false,其他数值返回true; 3.布尔类型: false返回false,true返回tr ...
- mui下拉上拉(明一)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
- Android中的消息处理机制
安卓中的消息处理机制主要涉及到5个概念 (1)消息类:Message,可以理解成一个数据单元: (2)消息队列类:Message Queue,存放通过Hander发布的消息,处理顺序类似于队列,按照先 ...
- MySQL学习——备份和还原
MySQL学习——备份和还原 摘要:本文主要学习了如何备份和还原数据库. 部分内容来自以下博客: https://www.cnblogs.com/chenmh/p/5300370.html 常用命令 ...
- php外挂python脚本抓取ajax数据
之前我写过一遍php外挂python脚本处理视频的文章.今天和大家分享下php外挂python实现输入关键字搜索的脚本 首先我们先来分析一波网站: http://www.dzdpw.com/s.php ...
- CentOS 7 部署 Redis(单机版)
一.部署环境说明 软件 版本 安装包 CentOS 7.2 CentOS 7.2 Redis 4.0.14 redis-4.0.14.tar.gz 二.开始部署 安装gcc依赖 [root@bmsof ...
- 7-8 矩阵A乘以B (15分)
7-8 矩阵A乘以B (15分) 给定两个矩阵A和B,要求你计算它们的乘积矩阵AB.需要注意的是,只有规模匹配的矩阵才可以相乘.即若A有Ra行.Ca列,B有Rb行.Cb列, ...
- cenos7 安装samba
1)安装samba应用# yum install samba samba-client2)启动Samba应用 systemctl start smb nmb3)Samba配置文件 /etc/samba ...