__declspec(dllimport)的小秘密(转)
昨天和同事使用一个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)的小秘密(转)的更多相关文章
- 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版本的代码,但 ...
- __declspec(dllimport)
我相信写WIN32程序的人,做过DLL,都会很清楚__declspec(dllexport)的作用,它就是为了省掉在DEF文件中手工定义导出哪些函数的一个方法.当然,如果你的DLL里全是C++的类的话 ...
- extern "C" __declspec(dllexport) __declspec(dllimport) 和 def
原文:extern "C" __declspec(dllexport) __declspec(dllimport) 和 def 前面的extern "C" _ ...
- __declspec(dllexport) & __declspec(dllimport)
__declspec(dllexport) 声明一个导出函数,是说这个函数要从本DLL导出.我要给别人用.一般用于dll中 省掉在DEF文件中手工定义导出哪些函数的一个方法.当然,如果你的DLL里全是 ...
- 浅谈__declspec(dllexport)和__declspec(dllimport)
__declspec(dllimport)和__declspec(dllexport)经常是成对的,在动态链接库中__declspec(dllexport)导出dll中的成员,__declspec(d ...
- 动态链接库(dll) __declspec(dllimport) __declspec(dllexport)
一. __declspec(dllexport) Microsoft 在 Visual C++ 的 16 位编译器版本中引入了 __export,使编译器得以自动生成导出名并将它们放到一个 .lib ...
- 理解 __declspec(dllexport)和__declspec(dllimport)
1.解决的问题: 考虑下面的需求,使用一个方法,一个是提供者,一个是使用者,二者之间的接口是头文件.头文件中声明了方法,在提供者那里方法应该被声明为__declspec(dllexport),在使用者 ...
- __declspec(dllimport)的作用
是时候总结一下__declspec(dllimport)的作用了.可能有人会问:__declspec(dllimport)和__declspec(dllexport)是一对的,在动态链接库中__dec ...
- __declspec(dllexport) 和 __declspec(dllimport)的作用
operatordll.h #include <iostream> #ifndef _WIN32 #define DLL_EXPORT#else #ifdef OPERATORDLL_EX ...
随机推荐
- 我的IT之路
在写这篇文章的时候内心是无比激动,因为这辈子是注定和IT打交道了. 都说大学时光是美好的,但却只有到了大四才知道时间是短暂的,也许和许多人一样,我的大学主要时光是在游戏中度过,1000多把的寒冰算是同 ...
- HDMI原理图信号PIN脚
HDMI(19Pin)/DVI(16 pin)的功能是热插拔检测(HPD),这个信号将作为主机系统是否对HDMI/DVI是否发送TMDS信号的依据.HPD是从显示器输出送往计算机主机的一个检测信号.热 ...
- 一步一步实现一个简单的OS(简单的让boot载入setup)
这次直接写用boot载入setup模块. 文件系统就先不弄了,以后再说, 咱先整个转简单的载入器. 我把软盘引导改成硬盘了,由于硬盘的读扇区函数简单一些. 这里没有做硬盘的mbr区,我认为在如今我的这 ...
- URL Handle in Swift (一) -- URL 分解
更新时间: 2018-6-6 在程序开发过程之中, 我们总是希望模块化处理某一类相似的事情. 在 ezbuy 开发中, 我接触到了对于 URL 处理的优秀的代码, 学习.改进.记录下来.希望对你有所帮 ...
- 开发ActiveX控件调用另一个ActiveX系列3——ActiveX调用另一个ActiveX
终于进入正题了,怎样在ActiveX中调用另一个ActiveX.我们的项目需要调用华视电子身份证识别仪的ActiveX控件 在这里有很多识别仪ActiveX插件下载:http://www.idukaq ...
- struct timeval 和 struct timespec
struct timeval { time_t tv_sec; suseconds_t tv_usec; }; 測试代码例如以下: #include <stdio.h> #include ...
- Centos 7.0设置静态IP
1.查看NetworkManager.service systemctl | grep "NetworkManager.service" 2.停止NetworkManager.se ...
- VIM中保存编辑的只读文件
如何在VIM中保存编辑的只读文件 你是否会和我一样经常碰到这样的情景:在VIM中编辑了一个系统配置文件,当需要保存时才发现当前的用户对该文件没有写入的权限.如果已 经做了很多修改,放弃保存的确很懊恼, ...
- freopen - C/C++文件输入输出利器
freopen以前经常使用,比较方便,可以当作模板,在中间替换为自己的代码即可使用. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include <stdio.h&g ...
- 《Java设计模式》之构建者模式
概述: 构造者模式(Builder Pattern):构造者模式将一个复杂对象的构造过程和它的表现层分离开来.使得相同的构建过程能够创建不同的表示,又称为生成器模式. Bu ...