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

不使用 __declspec(dllimport) 也能正确编译代码,但使用 __declspec(dllimport) 使编译器可以生成更好的代码。编译器之所以能够生成更好的代码,是因为它可以确定函数是否存在于 DLL 中,这使得编译器可以生成跳过间接寻址级别的代码,而这些代码通常会出现在跨 DLL 边界的函数调用中。但是,必须使用 __declspec(dllimport) 才能导入 DLL 中使用的变量。  

假设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导出函数,直接编译成对调入节的调用。

最新文章

  1. druid sql黑名单 报异常 sql injection violation, part alway true condition not allow
  2. PostgreSQL 杂志
  3. ubuntu下deb包的安装方法
  4. POJ3208 Apocalypse Someday(二分 数位DP)
  5. 简单回忆一下JavaScript中的数据类型
  6. 源代码解读Cas实现单点登出(single sign out)功能实现原理
  7. TCP/IP详解学习笔记(4)-ICMP协议,ping和Traceroute
  8. GDI泄露检测
  9. Sql Server中三种字符串合并方法的性能比较
  10. 微信小程序hidden
  11. linux上部署rmi+memcache服务
  12. python3使用ctypes在windows中访问C和C++动态链接库函数示例
  13. python Socket socketserver
  14. LeetCode 520 Detect Capital 解题报告
  15. JavaScript如何实现继承
  16. 重写$.ajax方法
  17. nginx反向代理 支持WebSocket
  18. spring mvc 接受前台json @RequestBody json 属性 空 使用 JsonProperty spring mvc 获取json转乘bean
  19. 【Linux】字符转换命令paste
  20. netif_receive_skb->__netif_receive_skb_core

热门文章

  1. CentOS虚拟机不能联网状况下yum方式从本地安装软件包
  2. SpringMVC_关于<url-pattern>
  3. Java数据库操作(JDBC)
  4. sql:sql server,MySQL,PostgreSQL的表,视图,存储过程结构查询
  5. Java 社区论坛 - Sym 1.5.0 发布
  6. 【javascript】javascript设计模式之单例模式
  7. Flex 加载pdf
  8. Gensim入门教程
  9. JS 日期与时间戳相互转化
  10. flask请求流程