浅谈__declspec(dllexport)和__declspec(dllimport)
__declspec(dllimport)和__declspec(dllexport)经常是成对的,在动态链接库中__declspec(dllexport)导出dll中的成员,__declspec(dllimport)导入外部dll中的成员。
但是有时候不使用dllimport和dllexport也能实现个基本的导出导入功能, 它们具有的功能如下:
1.dllimport/dllexport可以导入或者导出动态链接库中的全局变量,当然是用extern也可以实现同样的功能;
2.dllimport/dllexport的作用主要体现在导出类的静态成员方面,如果不使用它们,无法在正常是用外部dll中类的静态成员函数;
3.隐式使用dll时,不加dllimport/dllexport也是可以,使用上没什么区别,只是在生成的二进制代码上稍微有点效率损失;
4.使用dllimport/dllexport还可以体现编程语言的对称美。
以下是一个Demo实例:
====================================.h文件如下[DllExport.h]:================================================
#ifdef DLLEXPORT_EXPORTS
#define DLLEXPORT_API __declspec(dllexport)
#else
#define DLLEXPORT_API __declspec(dllimport)
#endif // class从dll中导出Demo
class DLLEXPORT_API CDllExport {
public: CDllExport(void);
}; //变量从dll中导出Demo
extern DLLEXPORT_API int nDllExport; //函数从dll中导出Demo
DLLEXPORT_API int fnDllExport(void);
====================================.cpp文件如下[DllExport.cpp]:==============================================
#include "DllExport.h" // 变量从Dll中导出Demo
DLLEXPORT_API int nDllExport=; // 函数从Dll中导出Demo
DLLEXPORT_API int fnDllExport(void) { return ; } // 类从Dll中导出Demo,以下为导出类的构造函数
CDllExport::CDllExport() { return; }
====================================调用文件如下[DemoEntry.cpp]:=============================================
#include"DllExport.h"
#include<iostream> int _tmain(int argc, _TCHAR* argv[])
{
int returncnt= fnDllExport();
std::cout<<returncnt<<std::endl;
system("pause");
return ; }
====================================================================================================
调用Dll过程编译器设置如下:


同样,使用.def文件也可以导出dll中的函数供外部调用,关于.def的使用如下:
1.LIBRARY语句说明.def文件相应的DLL;
2.EXPORTS语句后列出要导出函数的名称。可以在.def文件中的导出函数名后加@n,表示要导出函数的序号为n(在进行函数调用时,这个序号将发挥其作用);
3.def文件中的注释由每个注释行开始处的分号 (;) 指定,且注释不能与语句共享一行
以下是使用.def 文件导出DLL的Demo实例:
====================================.cpp文件如下[APIExport.cpp]:=============================================
int nTest=;//全局变量 int AddAndMulti(int a,int b)
{
return (a+b)*nTest;
} int _stdcall SubAndMulti(int a,int b)
{
return (a-b)*nTest;
} int _cdecl Multiply(int a,int b)
{
return a*b;
}
====================================.def文件如下[DllExport.def]:==============================================
LIBRARY DllExport_def
EXPORTS
AddAndMulti @3
SubAndMulti @5
Multiply @1
nTest DATA
====================================.cpp调用代码[DllLoadEntry.cpp]:============================================
// DllLoadEntry.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <iostream> using namespace std; //引用dll中的全局变量
extern int _declspec(dllimport) nTest; //声明函数,需与Dll中的函数定义一致(包括其函数调用修饰词)
int AddAndMulti(int a,int b); int _stdcall SubAndMulti(int a,int b); int _cdecl Multiply(int a,int b); //#pragma comment(lib,"DllExport_def.lib")
int _tmain(int argc, _TCHAR* argv[])
{
nTest=; cout<<AddAndMulti(,)<<endl;
cout<<SubAndMulti(,)<<endl;
cout<<Multiply(,)<<endl; system("pause"); return ;
}
====================================================================================================
编译环境设置如下:

当然也可以在代码中添加 #pragma comment(lib,"DllExport_def.lib")实现同样的效果,DLL和调用的exe在同一个目录下。
def和__declspec的使用区别:
VC++编译器会对__declspec导出的函数进行一定的变化,如下:__declspec(dllexport) int __stdcall Add()会转换为Add@0(),对于外部调用程序也是VC++时,只需要将编译产生的lib文件提供给调用者即可,而如果提供给语言程序调用,就不是那么方便了。此时,使用.def文件就可以让编译器不会对导出的函数名称进行修改。
浅谈__declspec(dllexport)和__declspec(dllimport)的更多相关文章
- __declspec(dllexport) 和 __declspec(dllimport)的区别
最近看MXNet的源码,其中c_api.h中发现遇到__declspec(dllexport) 和 __declspec(dllimport). __declspec(dllexport)用于导出符号 ...
- 理解 __declspec(dllexport)和__declspec(dllimport)
1.解决的问题: 考虑下面的需求,使用一个方法,一个是提供者,一个是使用者,二者之间的接口是头文件.头文件中声明了方法,在提供者那里方法应该被声明为__declspec(dllexport),在使用者 ...
- __declspec(dllexport) 和 __declspec(dllimport)的作用
operatordll.h #include <iostream> #ifndef _WIN32 #define DLL_EXPORT#else #ifdef OPERATORDLL_EX ...
- 通过宏定义将__declspec(dllexport)与__declspec(dllimport)的转化,实现库代码和使用代码使用同一份头文件
我们知道,在VC编程中,如果要编译成动态链接库,需要将函数.变量.类等导出,这时使用__declspec(dllexport).使用动态链接库时,需要在声明的时候有使用__declspec(dllim ...
- 【转载】 __declspec(dllexport) 和__declspec(dllimport)
转自:http://www.cppblog.com/Dutyboy/archive/2010/11/15/133699.html __declspec(dllexport) __declspec( ...
- __declspec(dllexport)和__declspec(dllimport) (——declspec方法创建dll的方法已验证ok)
转载:https://www.cnblogs.com/chengbing2011/p/4084125.html __declspec(dllimport)和__declspec(dllexport)经 ...
- __declspec(dllexport)
__declspec(dllexport) (2010-06-17 10:04:28) 转载▼ 标签: __declspec dllexport 导出 it 分类: C 先看代码:以下是在dev-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里全是 ...
随机推荐
- BestCoder Round #11 题解集合
1001.Alice and Bob 签到题*1,只要x * 2 == n && y * 2 == m就满足条件. var m, n, x, y : int64; begin whil ...
- Jsp开发自定义标签,自定义标签将字符串转成指定的时间格式显示
本例以将 字符串格式的时间转成指定的时间格式显示. 第一步.定义一个标签处理程序类,需要集成javax.servlet.jsp.tagext.TagSupport,代码如下: import java. ...
- mac 无法ssh localhost
mac 无法ssh localhost,错误提示:bash: /usr/local/bin/ssh_session: Permission denied在网上找了很久也没有找到解决方案,最后根据提示自 ...
- CentOS 常用命令大全(2)
系统 # uname -a # 查看内核/操作系统/CPU信息 # head -n 1 /etc/issue # 查看操作系统版本 # cat /proc/cpuinf ...
- useradd 和groupadd
1.作用useradd命令用来建立用户帐号和创建用户的起始目录,使用权限是终极用户.2.格式useradd [-d home] [-s shell] [-c comment] [-m [-k temp ...
- ruby学习网站
Ruby官方中文网(推荐): https://www.ruby-lang.org/zh_cn/ 国内非常不错的Ruby学习教程网站(推荐): http://www.yiibai.com/ruby Ru ...
- 浅析Oracle范式的概念(转载)
范式:英文名称是 Normal Form,它是英国人 E.F.Codd(关系数据库的老祖宗)在上个世纪70年代提出关系数据库模型后总结出来的,范式是关系数据库理论的基础,也是我们在设计数据库结构过程中 ...
- 数据结构-AVL树
实现: #ifndef AVL_TREE_H #define AVL_TREE_H #include "dsexceptions.h" #include <iostream& ...
- .net异常小总
1. ExecuteReader:CommandText属性尚未初始化 即:没有对sqlCommand对象的CommandText属性赋值,即没有写sql语句. 2. 由于代码已经过优化或者本机框 ...
- initWithFrame 和 initWithCoder
当我们所写的程序里没用用Nib文件(XIB)时,用代码控制视图内容,需要调用initWithFrame去初始化 - (id)initWithFrame:(CGRect)frame { if (self ...