是时候总结一下__declspec(dllimport)的作用了。可能有人会问:__declspec(dllimport)和__declspec(dllexport)是一对的,在动态链接库中__declspec(dllexport)管导出,__declspec(dllimport)管导出,就像一个国家一样,有出口也有进口,有什么难理解的呢?这是一种很自然的思路,开始我也是这样理解。

但是在两年前的一个项目中,我发现不用__declspec(dllimport)似乎也可以。比如现在我新建一个使用共享MFC DLL的规则DLL工程:DllDlg。然后我新建两个文件:DllApi.h和DllApi.cpp。DllApi.h作为接口文 件,DllApi.cpp作为实现文件。

接着在DllApi.h声明一个函数:

__declspec(dllexport) void HelloWorld(); 

在DllApi.cpp写这个函数的实现:

void HelloWorld()
{  AfxMessageBox(_T("HelloWorld"));
}  

这样外部的应用程序或dll就能调用HelloWorld函数。这里要特别提醒的是:有些网友说要把DllApi.h中的__declspec(dllexport) void HelloWorld();改为__declspec(dllimport) void HelloWorld();才能提供给外部调用,实际上这并不需要,这个我已经测试过。从那时我就产生一个疑问:照这样,像类似下面的:

#ifdef _EXPORTING
#define API_DECLSPEC    __declspec(dllexport)
#else
#define API_DECLSPEC    __declspec(dllimport)
#endif  

是不是就只剩下一种作用:让外部调用者看得更自然些,知道哪些接口是自己工程需要导入的?__declspec(dllimport)是不是一点实际作用都没有呢?这个疑问一直盘旋在我的脑海。直到最近,我在CSDN论坛上发了一个帖子:

__declspec(dllimport) 的作用到底在哪里呢?

总结了各位大虾的发言,特得出如下结论: 
1. 在导入动态链接库中的全局变量方面起作用:
使用类似

#ifdef _EXPORTING
#define API_DECLSPEC    __declspec(dllexport)
#else
#define API_DECLSPEC    __declspec(dllimport)
#endif  

可以更好地导出dll中的全局变量,比如按照的宏,可以在dll中这样导出全局变量:

API_DECLSPEC CBtt g_Btt;  

然后在调用程序这样导入:

API_DECLSPEC CBtt g_Btt;  

当然也可以使用extern关键字,比如在dll中这样导出全局变量:

CBtt g_Btt; 

然后在调用程序这样导入:

extern CBtt g_Btt;  

但据说使用__declspec(dllimport)更有效。

2. __declspec(dllimport)的作用主要体现在导出类的静态成员方面,
比如在动态链接库中定义这样一个导出类:

class __declspec(dllexport) CBtt
{
public:  CBtt(void);  ~CBtt(void);
public:  CString m_str;  static int GetValue()  {  return m_nValue;  }
private:  static int m_nValue;
};  

照上面这样声明,外部虽然可以使用CBtt类,但不能使用CBtt类的GetValue函数,一使用就会出现无法解析的外部符号 "public: static int CBtt::m_nValue" (?m_nValue@CBtt@@2HA)。只有如下声明才能使用CBtt类的GetValue函数:

#ifdef _EXPORTING
#define API_DECLSPEC    __declspec(dllexport)
#else
#define API_DECLSPEC    __declspec(dllimport)
#endif
class API_DECLSPEC CBtt
{
public:  CBtt(void);  ~CBtt(void);
public:  CString m_str;  static int GetValue()  {  return m_nValue;  }
private:  static int m_nValue;
};  

3. 使用隐式使用dll时,不加__declspec(dllimport)完全可以,使用上没什么区别,只是在生成的二进制代码上稍微有点效率损失。

a、 不加__declspec(dllimport)时,在使用dll中的函数时,编译器并不能区别这是个普通函数,还是从其它dll里导入的函数,所以其生 成的代码如下:

call 地址1

地址1:
jmp 实际函数地址

b、有 __declspec(dllimport)时,编译器知道这是要从外部dll导入的函数,从而在生成的exe的输入表里留有该项,以便在运行 exe,PE载入器加载exe时对输入地址表IAT进行填写,这样生成的代码如下:

call dword ptr[输入表里哪项对应的内存地址] (注意:现在就不需要jmp stub了)。这里
有兴趣的朋友可以参看《编译原理》和 PE文件格式。

4.使用__declspec(dllimport)体现了语言的一种对称美,比如虽然!true就是表示false,但是我们还是需要false这个关键字,这里体现了一种对称美。

在此特别感谢CSDN的众位大侠:superdiablo、wltg2001、ccpaishi、jszj、WizardK、hurryboylqs、jingzhongrong、jameshooo、glacier3d、winnuke、starnight1981、laiyiling、yang79tao、ForestDB、zhouzhipen、lxlsymbome、Beyond_cn。

总结一下__declspec(dllimport)的作用相关推荐

  1. 从static变量导出问题解析 __declspec(dllexport) 和 __declspec(dllimport)的作用

    这段时间要把tinyxml从静态库弄成动态库,要用到__declspec(dllexport)和__declspec(dllimport)来导出dll和lib文件.终于弄明白了export和impor ...

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

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

  3. __declspec(dllimport)

    我相信写WIN32程序的人,做过DLL,都会很清楚__declspec(dllexport)的作用,它就是为了省掉在DEF文件中手工定义导出哪些函数的一个方法.当然,如果你的DLL里全是C++的类的话 ...

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

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

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

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

  6. 关于__declspect(dllexport) 和 __declspec(dllimport)的使用

    __declspec(dllexport) 声明一个导出函数,是说这个函数要从本dll中导出,提供给别人用. 省掉在DEF文件中手工定义导出哪些函数的一个方法.当然,如果你的DLL里全是C++类的话, ...

  7. 【转载】__declspec(dllimport) __declspec(dllexport)

    https://blog.csdn.net/fsdad/article/details/115632555 一.基本概念 _declspec(dllexport)与_declspec(dllimpor ...

  8. 关于__declspec(dllimport)的理解

    一.基本概念 _declspec(dllexport)与_declspec(dllimport)都是DLL内的关键字,即导出与导入.他们是将DLL内部的类与函数以及数据导出与导入时使用的. 主要区别在 ...

  9. (转)__declspec(dllimport)和__declspec(dllexport)的区别,以及有关c/c++调用约定

    DLL可以使用两种方法将公共符号导入到应用程序中或从 DLL 导出函数: 生成 DLL 时使用模块定义 (.DEF) 文件.  在主应用程序的函数定义中使用 __declspec(dllimport) ...

  10. __declspec(dllexport)、__declspec(dllimport)详解

    在Visual studio中新建DLL项目时编译器会自动生成下面这样的宏定义: #ifdef DLL_EXPORTS #define DLL_API __declspec(dllexport) #e ...

最新文章

  1. Swift SB 容器 Container View使用
  2. 对象属性操作函数:hasattr(),getattr(),setattr()
  3. 别把客户当傻子,延期交货得这么谈!
  4. 北工大计算机网络基础期末考试,2013北工大计算机网络应用复习提纲整理版.doc...
  5. 139团队(大型研发团队,大型敏捷开发团队,大型团队结构,敏捷绩效管理)...
  6. 使用 imitator 实现前后端分离开发中的数据模拟与静态资源映射
  7. FFmpeg合并多个ts视频文件
  8. java生成背景透明的png图片,Java生成背景透明的png图片
  9. IM多点登录与消息漫游架构随想
  10. 基于SPSS的正态性检验方法汇总——以个股收益率为例(超详细)
  11. 英语不规则动词变化时态变化表
  12. 东北大学——考研复试——计算机网络——2014年
  13. 安装教程_Mac Adobe CC 2020 安装教程
  14. 9 与python2交互
  15. jenkins自动打包报错:cannot find symbol
  16. mysql利用cpu率高_MySQL CPU 使用率高的原因和解决方法
  17. 让View具有弹性效果的动画——SpringAnimation
  18. 工作任务清单怎么写效率更高
  19. 基于OpenGL的3D天空仿真
  20. 手机vnc远程桌面,手机vnc远程桌面教程加配置说明

热门文章

  1. 《霍比特人2:史矛革之战》BD高清 电影 下载 [中文字幕]
  2. 怎么利用pytorch训练好的模型测试单张图片
  3. oppo手机显示服务器连接错误,OPPO手机连不上wifi怎么办?OPPO连不上wifi的四种解决方法...
  4. 如何用Intel主板集成的RAID控制器(Intel RST)实现硬盘提速与硬盘数据恢复
  5. win7系统配置时间服务器,与Internet时间服务器同步 设Win7精确时间
  6. JS简单总结(前端ES6和JQ)
  7. linked list C++实现
  8. 情缘难舍 愿为一叶扁舟
  9. python代写学生作业_data留学生作业代做、代写Python程序设计作业、代做Python实验作业...
  10. 判断是否为IE浏览器