在Windows DLL编程时,可使用__declspec(dllimport)关键字导入函数或者变量。

函数的导入
当你需要使用DLL中的函数时,往往不需要显示地导入函数,编译器可自动完成。但如果你显示地导入函数,编译器会产生质量更好的代码。由于编译器确切地知道了一个函数是否在一个DLL中,它就可以产生更好的代码,不再需要间接的调用转接。
Win32的PE格式(Portable Executable Format)把所有导入地址放在一个导入地址表中。下面用一个具体实例说明使用__declspec(dllimport)导入函数和不使用的区别:
假设func是一个DLL中的函数,现在在要生成的.exe的main函数中调用func函数,并且不显示地导入func函数(即没有:__declspec(dllimport)),代码示例如下:
int main()
{
func();
}
编译器将产生类似这样的调用代码:
call func
然后,链接器把该调用翻译为类似这样的代码:
call 0x40000001       ; ox40000001是"func"的地址
并且,链接器将产生一个 Thunk,形如:
0x40000001: jmp DWORD PTR __imp_func
这里的imp_func是func函数在.exe的导入地址表中的函数槽的地址。然后,加载器只需要在加载时更新.exe的导入地址表即可。
而如果使用了__declspec(dllimport)显示地导入函数,那么链接器就不会产生Thunk(如果不被要求的话),而直接产生一个间接调用。因此,下面的代码:
__declspec(dllimport) void func1(void);
    void main(void)
    {
        func1();
    }
将调用如下调用指令:
call DWORD PTR __imp_func1
因此,显示地导入函数能有效减少目标代码(因为不产生Thunk)。另外,在DLL中使用DLL外的函数也可以这样做,从而提高空间和时间效率。
变量的导入
与函数不同的是,在使用DLL中的变量时,需要显示地导入变量。使用__declspec(dllimport)关键字导入变量。若在DLL中使用.def导出变量,则应使用DATA修饰变量,而不是使用已经被遗弃的CONSTANT。因为CONSTANT可能需要使用指针间接访问变量,不确定什么时候会出问题。

先看代码:以下是在dev-c++里建立自已的dll时的dll.h里面的代码,这里面有一个:_declspec(dllexport)

#ifndef _DLL_H_
#define _DLL_H_//防重复定义

#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */

DLLIMPORT void HelloWorld (void);

#endif /* _DLL_H_ */

上面代码里面的_delcspce(dllexport)被定义为宏,这样可以提高程序的可读性!这个的作是是将函数定义为导出函数,也就是说这个函数要被包含这个函数的程序之外的程序调用!本语句中就是:void Helloword(void):

摘自msdn:在 32 位编译器版本中,可以使用 __declspec(dllexport) 关键字从 DLL 导出数据、函数、类或类成员函数。__declspec(dllexport) 将导出指令添加到对象文件

若要导出函数,__declspec(dllexport) 关键字必须出现在调用约定关键字的左边(如果指定了关键字)。例如:

__declspec(dllexport) void __cdecl Function1(void);

若要导出类中的所有公共数据成员和成员函数,关键字必须出现在类名的左边,如下所示:

class __declspec(dllexport) CExampleExport : public CObject
{ ... class definition ... };

生成 DLL 时,通常创建一个包含正在导出的函数原型和/或类的头文件,并将 __declspec(dllexport) 添加到头文件中的声明。若要提高代码的可读性,请为 __declspec(dllexport) 定义一个宏并对正在导出的每个符号使用该宏:

#define DllExport   __declspec( dllexport ) 

__declspec(dllexport) 将函数名存储在 DLL 的导出表中。

若要确定用于导出函数的方法(.def 文件或 __declspec(dllexport) 关键字),请回答下列问题:

  • 是否要一直添加附加的导出函数?

  • 谁要使用 DLL?例如,是由许多无法重新生成的可执行文件使用的第三方 DLL 还是仅由可以轻松重新生成的应用程序使用的 DLL?

使用 .DEF 文件的优缺点

在 .def 文件中导出函数使您得以控制导出序号。当将附加的导出函数添加到 DLL 时,可以给它们分配更高的序号值(高于任何其他导出函数)。当您进行此操作时,使用隐式链接的应用程序不必与包含新函数的新导入库重新链接。这非常重要,例如,在设计将由许多应用程序使用的第三方 DLL 时。可以通过添加附加功能不断地增强 DLL,同时确保现有应用程序继续正常使用新的 DLL。MFC DLL 是使用 .def 文件生成的。

使用 .def 文件的另一个优点是:可以使用 NONAME 属性导出函数,该属性仅将序号放到 DLL 的导出表中。对具有大量导出函数的 DLL,使用 NONAME 属性可以减小 DLL 文件的大小。有关编写模块定义语句的信息,请参见模块定义语句的规则。有关序号导出的更多信息,请参见按序号而不是按名称从 DLL 导出函数。

使用 .def 文件的主要缺点是:在 C++ 文件中导出函数时,必须将修饰名放到 .def 文件中,或者通过使用外部“C”用标准 C 链接定义导出函数,以避免编译器进行名称修饰。

如果需要将修饰名放到 .def 文件中,则可以通过使用 DUMPBIN 工具或 /MAP 链接器选项来获取修饰名。请注意,编译器产生的修饰名是编译器特定的。如果将 Visual C++ 编译器产生的修饰名放到 .def 文件中,则链接到 DLL 的应用程序必须也是用相同版本的 Visual C++ 生成的,这样调用应用程序中的修饰名才能与 DLL 的 .def 文件中的导出名相匹配。

使用 __declspec(dllexport) 的优缺点

使用 __declspec(dllexport) 非常方便,因为不必考虑维护 .def 文件和获取导出函数的修饰名。例如,如果您设计的 DLL 供自己控制的应用程序使用,则此方法很适用。如果通过新的导出函数重新生成 DLL,还必须重新生成应用程序,因为如果使用不同版本的编译器进行重新编译,则导出的 C++ 函数的修饰名可能会发生变化。

Windows DLL编程中的导入导出:__declspec(dllimport) ,__declspec(dllexport) ,相关推荐

  1. 在DLL编程中调用模版类时出现的类似class“XXX”需要有 dll 接口由 class“XXX”的客户端使用的warning的解决方案...

    在DLL编程中, 如果调用模版类, 则可能出现类似以下的错误(以CString的使用为例): warning C4251: "CLogFile::m_strFileName":  ...

  2. mysql navicat导入bcp_SQL Server中BCP导入导出用法详解

    bcp命令是SQL Server提供的一个快捷的数据导入导出工具.使用它不需要启动任何图形管理工具就能以高效的方式导入导出数据.bcp是SQL Server中负责导入导出数据的一个命令行工具,它是基于 ...

  3. Windows用户界面编程中的界面闪烁问题

    http://yyf9989.cnblogs.com/archive/2005/09/02/228320.html Windows用户界面编程中的界面闪烁问题 南京千里独行版权所有转载请保留本信息 在 ...

  4. windows备份环境变量(导入导出)

    windows备份环境变量(导入导出) 导出(备份) win+r regedit 回车 系统环境变量 地址栏输入 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentContro ...

  5. C#窗体将DGV控件中数据导入导出Excel表

    目录 界面图: 效果视频: 一:将DGV数据导出到Excel表中 二:将Excel表数据导入到DGV中 三:界面全部代码 界面图: 效果视频: DGV数据导入导出Excel 一:将DGV数据导出到Ex ...

  6. oracle中数据导入导出问题

    在日常生活中,我们有时难免要对一些系统进行移植,移植的时候,数据库中的数据问题就需要在不同的服务器上移动,这时就涉 及到数据的导入导出问题,这里我给大家介绍一些oracle数据的导入和导出问题. or ...

  7. HZYWX-技术交流-开发中的导入导出

    1 背景 需求: 项目需求,导出excel或word: 批量数据导入: - 导入导出插件(API): 前端导出(jquery.wordexport.js.tableExport.js.Blob对象.x ...

  8. Windows图形编程 中的一个例程所引发的收获和思考

    作者:朱金灿 来源:http://blog.csdn.net/clever101/ 袁峰大侠著的<Windows图形编程>是一本学习<Windows图形编程>的好书.书中的第二 ...

  9. 在IOS中实现导入导出文档

    导入&导出文档时IOS开发者经常面临的开发需求.例如你开发一个文档阅读器允许用户导入他的文档到你的应用中以便离线阅读.又如,你的阅读器可以导出文档以便其他应用使用. 这篇文章,将介绍各种IOS ...

最新文章

  1. 排序算法之冒泡,选择,插入
  2. C++ 动态库导出函数名“乱码”及解决
  3. C语言断言assert()函数
  4. python3下的paramiko 安装
  5. 64位Ubuntu kylin 16.04使用fastboot下载内核到tiny4412开发板
  6. OC Swift 走马灯效果
  7. 提高单片机设计的10个细节
  8. oracle manager 配置,Oracle Net Manager 基本配置
  9. 避免Unity变量初始化错误的8条建议
  10. 【python】*与** 参数问题
  11. 【车牌识别】基于matlab GUI BP神经网络车牌识别(带面板)【含Matlab源码 858期】
  12. 侵入式框架和非侵入式框架的区别
  13. Raki的读paper小记:RoBERTa: A Robustly Optimized BERT Pretraining Approach
  14. R语言 聚类分析代码 系统聚类 K均值聚类 可视化
  15. UIImagePickerController本地化控件文字
  16. 三位数的茎叶图怎么看_三位数的茎叶图
  17. 对于程序员而言,是否金三银四才是最佳跳槽季
  18. PHP-FPM的PM配置参数说明
  19. 什么是网页设计中的滚动设计?如何进行滚动设计?
  20. 计算机dns怎么设置方法,电脑的dns怎么设置具体方法

热门文章

  1. com.mysql.cj.exceptions.CJCommunicationsException
  2. 第1节、一个萝卜一个坑——计数排序
  3. 在web中如何调整上传过的图片方向 (exif)
  4. 1、暴力破解与实用性原则
  5. 如何把电脑中mkv视频文件刻录成蓝光视频光盘
  6. 拿到亚马逊offer的经历 (毫无保留)
  7. 中国脱粒机行业市场供需与战略研究报告
  8. 期货秒交易(期货秒懂百科)
  9. 全球及中国成人口腔护理产品行业市场供给分析与投资战略规划研究报告2022-2028年
  10. 智慧管廊数字管道建设整体技术方案2023(word)