昨天和同事使用一个dll(lib+dll)的时候,发现他在引用头文件是,并没有使用__declspec(dllimport),但是程序完全运行正常,不明觉厉下,去网上翻了下资料,原来是链接器的原因,这里贴一个转帖,已经写得很清楚了。

邓立波 深圳,2008-6

作者联系方式:

email:    libodeng@gmail.com

msn:     libodeng@gmail.com

按照MSDN说明,当链接dll的导出函数时,只需要包含头文件和lib,__declspec(dllimport)修饰符不是必须的,但加上该修饰能使导出函数的调用效率更高。那么,究竟原因是什么?

假设dll导出了一个函数:
extern "C" __declspec(dllexport) void fun();
如果程序中声明不加__declspec(dllimport),查看调用fun()函数的汇编代码:
    004010AD   call        fun (004010d8)
其中fun被定义为一个标号(label),如下:
fun:
    004010D8   jmp         dword ptr [__imp__fun (0040e0e8)]
上面的符号__imp__fun指向的地址为fun()函数在exe中的导入节。

当声明加上__declspec(dllimport)后,查看调用fun()函数的汇编代码:
    004010AB   call        dword ptr [__imp__fun (0040e0e8)]

从上面可以看出,加上__declspec(dllimport),编译器链接dll将省略一条jmp语句。
这是因为:

1。如果导出函数的声明没有用__declspec(dllimport) 修饰的话,编译器并不知道这个函数是由DLL导出的,所以编译器就把这个函数当作普通的外部引用来对待,产生一个外部引用的符号等着链接器解析。当链接器工作的时候,它是不能修改编译器生成的结果,所以会将该符号解析为对相应函数调入节的间接调用。

2。如果导出函数的声明用__declspec(dllimport) 修饰的话,编译器一开始就知道这个函数是DLL导出函数,直接编译成对调入节的调用。

原文:http://libo.deng.blog.163.com/blog/static/40157422200851124138373/

__declspec(dllimport)的小秘密(转)的更多相关文章

  1. VC++ : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::basic_string<wchar_t,struct std::char_traits<wchar_t>

    最近学习Google Breakpad,将其用在了自己的项目中,编译的版本为VS2010,没有什么问题.但是为了和之前的程序兼容,需要使用VS2008版本的程序,于是又编译了VS2008版本的代码,但 ...

  2. __declspec(dllimport)

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

  3. extern "C" __declspec(dllexport) __declspec(dllimport) 和 def

    原文:extern "C" __declspec(dllexport) __declspec(dllimport) 和 def 前面的extern "C"  _ ...

  4. __declspec(dllexport) & __declspec(dllimport)

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

  5. 浅谈__declspec(dllexport)和__declspec(dllimport)

    __declspec(dllimport)和__declspec(dllexport)经常是成对的,在动态链接库中__declspec(dllexport)导出dll中的成员,__declspec(d ...

  6. 动态链接库(dll) __declspec(dllimport) __declspec(dllexport)

    一. __declspec(dllexport) Microsoft 在 Visual C++ 的 16 位编译器版本中引入了 __export,使编译器得以自动生成导出名并将它们放到一个 .lib ...

  7. 理解 __declspec(dllexport)和__declspec(dllimport)

    1.解决的问题: 考虑下面的需求,使用一个方法,一个是提供者,一个是使用者,二者之间的接口是头文件.头文件中声明了方法,在提供者那里方法应该被声明为__declspec(dllexport),在使用者 ...

  8. __declspec(dllimport)的作用

    是时候总结一下__declspec(dllimport)的作用了.可能有人会问:__declspec(dllimport)和__declspec(dllexport)是一对的,在动态链接库中__dec ...

  9. __declspec(dllexport) 和 __declspec(dllimport)的作用

    operatordll.h #include <iostream> #ifndef _WIN32 #define DLL_EXPORT#else #ifdef OPERATORDLL_EX ...

随机推荐

  1. SVN客户端忽略无关文件

    修改前请先备份文件 ~/.subversion/config. 1,打开Terminal,输入命令: $ open ~/.subversion/config   2,在打开的文件中寻找:`global ...

  2. 解决mysql数据库乱码问题

    MySQL的SQL语言是用于访问数据库的最常用标准化语言.MySQL软件采用了双授权政策,它分为社区版和商业版,由于其体积小.速 度快.总体拥有成本低,尤其是开放源码这一特点,一般中小型网站的开发都选 ...

  3. 概率图模型(PGM)学习笔记(二)贝叶斯网络-语义学与因子分解

    概率分布(Distributions) 如图1所看到的,这是最简单的联合分布案例,姑且称之为学生模型. 图1 当中包括3个变量.各自是:I(学生智力,有0和1两个状态).D(试卷难度,有0和1两个状态 ...

  4. MariaDB mysql 比较区别 选择

    MariaDB数据库管理系统是MySQL的一个分支 开发这个分支的原因之一是:甲骨文公司收购了MySQL后,有将MySQL闭源的潜在风险,因此社区采用分支的方式来避开这个风险. MariaDB的目的是 ...

  5. 22 nginx配置与集群

    一:编译nginx ,并配置 Cd /app/pcre-8.12 ./configure Make && make install Cd nginx-1.2.7 ./configure ...

  6. 知识复习(LDT+TSS+GATE+INTERRUPT)

    [1]README 1.0)由于实现进程的切换任务,其功能涉及到 LDT + TSS +GATE + INTERRUPT:下面我们对这些内容进行复习: 1.1) source code from or ...

  7. 输出 pdf

    jar 包 :core-renderer.jar  iText-2.0.8.jar   iTextAsian.jar 方式1: import java.io.FileNotFoundException ...

  8. 【BZOJ4568】[Scoi2016]幸运数字 倍增+线性基

    [BZOJ4568][Scoi2016]幸运数字 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念 ...

  9. SQL中的四种连接方式

    转自:http://www.cnblogs.com/afirefly/archive/2010/10/08/1845906.html 联接条件可在FROM或WHERE子句中指定,建议在FROM子句中指 ...

  10. TCP/UDP server

    Simple: Sample TCP/UDP server https://msdn.microsoft.com/en-us/library/aa231754(v=vs.60).aspx Simple ...