VC 静态库与动态库(三)动态库创建与使用_隐式链接
动态库分为二种,一种隐式链接,另一种显示调用。不论哪种动态库,本质都是运行时动态加载
隐式链接:程序运行时,由编译系统自动加载动态库,然后根据程序的引入表进行重定位,当程序退出时自动卸载动态库
显示调用:程序运行时,在需要使用动态库时手动使用LoadLibrary进行加载,当不需要动态库时使用FreeLibrary进行卸载
动态库创建:
1.新建项目,创建项目和解决方案
DynamicLibrary 这是动态库项目
G:\C++Learn\Library Library文件夹用于存放库相关文件,包含静态库与动态库工程和解决方案
DynamicLibraryDemo 动态库解决方案名称
2.点击下一步,出现如下界面
选择DLL,选择导出符号,如果需要使用MFC就勾选上,最后点击完成
3.然后VS左边解决方案管理器会显示相关文件
这就是个最简单的动态库,编译生成下
4.文件夹生成了相关文件
解决方案目录:
解决方案目录下,项目文件夹DynamicLibrary,Debug解决方案调试目录下面就存放了编译生成的 输入库(.lib)和动态链接库(.dll)
回顾下静态库生成,一对比就会发现静态库生成时没有.dll文件
5. 动态库比静态库生成的文件稍显复杂些,这里稍微介绍下
首先看下DynamicLibrary.h,这里由于在第二步时勾选了导出符号,所以VS会默认产生一个与工程
同名的.h文件包含示例代码,导出了相关类和函数帮助我们了解动态库使用
注意:如果没有勾选导出符号,是不会生成DynamicLibrary.h文件的,需要自己进行创建.h进行导出
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 DYNAMICLIBRARY_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// DYNAMICLIBRARY_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef DYNAMICLIBRARY_EXPORTS
#define DYNAMICLIBRARY_API __declspec(dllexport)
#else
#define DYNAMICLIBRARY_API __declspec(dllimport)
#endif // 此类是从 DynamicLibrary.dll 导出的
class DYNAMICLIBRARY_API CDynamicLibrary {
public:
CDynamicLibrary(void);
// TODO: 在此添加您的方法。
}; extern DYNAMICLIBRARY_API int nDynamicLibrary; DYNAMICLIBRARY_API int fnDynamicLibrary(void);
7-11行的宏定义在不同工程中起到不同的作用。
在当前动态库工程中由于定义了DYNAMICLIBRARY_EXPORTS宏, 所以这个宏表示的是导出
而在外部程序,虽然使用动态库包含了这个头文件,但是没有定义这个宏,所以这个宏表示的是导入
13-22行用到的宏也是一样的作用,在当前动态库工程中代表的是导出,在外部程序中代表的导入
可能有人会发现工程下文件并没有定义这个宏,为什么会说这个宏己经被定义呢?
答案就是这个宏在VS的预处理器定义了,创建动态库项目时,VS会自动帮你在预处理器中添加一个与工程项目
名相同,全部大写后面加上_EXPORTS的一个宏
当然也可以在头文件中修改宏的名字,但是相应的预处理器定义里也得保持一致
DynamicLibrary.cpp文件
// DynamicLibrary.cpp : 定义 DLL 应用程序的导出函数。
//
#include "stdafx.h"
#include "DynamicLibrary.h"
// 这是导出变量的一个示例
DYNAMICLIBRARY_API int nDynamicLibrary=0;
// 这是导出函数的一个示例。
DYNAMICLIBRARY_API int fnDynamicLibrary(void)
{
return 42;
}
// 这是已导出类的构造函数。
// 有关类定义的信息,请参阅 DynamicLibrary.h
CDynamicLibrary::CDynamicLibrary()
{
return;
}
6. 给CDynamicLibrary类添加一个MathAdd方法,另外添加一个全局函数MathSub. 最后编译生成
DynamicLibrary.h
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 DYNAMICLIBRARY_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// DYNAMICLIBRARY_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef DYNAMICLIBRARY_EXPORTS
#define DYNAMICLIBRARY_API __declspec(dllexport)
#else
#define DYNAMICLIBRARY_API __declspec(dllimport)
#endif
// 此类是从 DynamicLibrary.dll 导出的
class DYNAMICLIBRARY_API CDynamicLibrary {
public:
CDynamicLibrary(void);
int MathAdd(int a,int b);//加法计算(类成员函数)
};
DYNAMICLIBRARY_API int MathSub(int a ,int b);//减法计算(全局函数)
DynamicLibrary.cpp
// DynamicLibrary.cpp : 定义 DLL 应用程序的导出函数。
//
#include "stdafx.h"
#include "DynamicLibrary.h"
//减法计算(全局函数)
DYNAMICLIBRARY_API int MathSub(int a ,int b)
{
return a - b;
}
// 这是已导出类的构造函数。
// 有关类定义的信息,请参阅 DynamicLibrary.h
CDynamicLibrary::CDynamicLibrary()
{
return;
}
//加法计算(类成员函数)
int CDynamicLibrary::MathAdd(int a,int b)
{
return a + b;
}
隐式链接项目创建:
1.给解决方案添加一个新的控制台项目HideLink用于测试动态库,创建完成后设置为启动项目
2.HideLink.cpp添加相关代码
// HideLink.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "../DynamicLibrary/DynamicLibrary.h" //动态库头文件
#pragma comment(lib,"../Debug/DynamicLibrary.lib")//引入动态库.lib文件
int _tmain(int argc, _TCHAR* argv[])
{
//使用动态库中CDynamicLibrary类,调用其中的MathAdd方法
CDynamicLibrary dynamicLib;
int nResult = dynamicLib.MathAdd(1,2);
printf("1 + 2 = %d\r\n",nResult);
//调用动态库中的全局函数MathSub
nResult = MathSub(5,1);
printf("5 - 1 = %d\r\n",nResult);
getchar();
return 0;
}
3. 编译运行HideLink, 查看相关信息
控制台输出调试信息,下方的模快里不单有HideLink.exe以及系统dll,还多了个动态库DynamicLibrary.dll
总结:虽然动态库的隐式链接方式和静态库调用代码差不多,但是二者内部实现是有明显差别的。
静态库在链接阶段是直接打包到程序中,而动态库的隐式链接在链接阶段只是把用到的函数声明加入
到引用表中,并不会把函数实现代码加入程序中,更不会把整个动态库打包进程序
VC 静态库与动态库(三)动态库创建与使用_隐式链接的更多相关文章
- [转]静态库、动态库,dll文件、lib文件,隐式链接、显式链接
转自:https://blog.csdn.net/dcrmg/article/details/53427181 静态链接.动态链接 静态库和动态库分别应用在静态链接方式和动态链接方式中,所谓静态链接方 ...
- 静态库、动态库,dll文件、lib文件,隐式链接、显式链接浅见
静态链接.动态链接 静态库和动态库分别应用在静态链接方式和动态链接方式中,所谓静态链接方式是指在程序执行之前完成所有的链接工作,把静态库一起打包合入,生成一个可执行的目标文件(EXE文件).所谓动态链 ...
- Selenium4+Python3系列(六) - Selenium的三种等待,强制等待、隐式等待、显式等待
为什么要设置元素等待 直白点说,怕报错,哈哈哈! 肯定有人会说,这也有点太直白了吧. 用一句通俗易懂的话就是:等待元素已被加载完全之后,再去定位该元素,就不会出现定位失败的报错了. 如何避免元素未加载 ...
- VC学习笔记---ATL MFC CLR三个库的区别
MFC.ATL和CLR是VC2005内置的三大库,涵盖了Windows的各种开发方法和开发应用.当然关于C++开发的库不止这三个,不过这三个是微软推荐. 从编程所处层次而言,WIN32为最底层,其次是 ...
- Matlab:高阶常微分三种边界条件的特殊解法(隐式Euler)
函数文件1: function b=F(f,x0,u,h) b(1,1)=x0(1)-h*x0(2)-u(1); b(2,1)=x0(2)+h*x0(1)^2-u(2)-h*f; 函数文件2: fun ...
- python+selenium基础篇,三种等待方式,显示、隐式、强制等待
1.显示等待: from selenium import webdriver from time import sleep from selenium.webdriver.support.ui imp ...
- 1.改变项目 动态库、静态库属性。 2.使用运行库 /MD、/MT、/LD说明
/MD./MT./LD(使用运行库) 有关 C 运行库以及使用 /clr(公共语言运行时编译) 进行编译时要使用哪些库的更多信息,请参见 CRT 库功能. 传递给链接器的给定调用的所有模块都必须使用相 ...
- 【1】基于OpenCV的DLL动态库隐式连接
1DLL的作用 DLL是一个包含可由多个程序同时使用的代码和数据的库.例如:在Windows操作系统中,Comdlg32 DLL执行与对话框有关的常见函数.因此,每个程序都可以使用该DLL中包含的功能 ...
- DLL动态库的创建,隐式加载和显式加载
动态库的创建 打开VS,创建如下控制台工程,工程命名为DllTest: 在弹出的对话框中选择"DLL"后单击"完成"按钮: 在工程中新建DllTest.h和Dl ...
随机推荐
- Javascript定时器只能执行一次
为了说明问题,代码很短 <script> var test = function(){ console.log('a') } timer1 = setInterval(test(), 10 ...
- Python进阶-XVIII 封装、(属性、静态方法、类方法)语法糖、反射
1.封装 类中的私有化:属性的私有化和方法的私有化 会用到私有的这个概念de场景 1.隐藏起一个属性 不想让类的外部调用 2.我想保护这个属性,不想让属性随意被改变 3.我想保护这个属性,不被子类继承 ...
- Java进阶的道路,怎么成为大牛?
已然励志在java路上走的更远,那就有必要了解java的途径.先看图 image.png 愈加细化的细节如下 一: 编程基础 不管是C仍是C++,不管是Java仍是PHP,想成为一名合格的程序员,根 ...
- [LOJ 2133][UOJ 131][BZOJ 4199][NOI 2015]品酒大会
[LOJ 2133][UOJ 131][BZOJ 4199][NOI 2015]品酒大会 题意 给定一个长度为 \(n\) 的字符串 \(s\), 对于所有 \(r\in[1,n]\) 求出 \(s\ ...
- 使用App.Metrics监控消息队列
使用App.Metrics监控消息队列 一.简介 App Metrics是一个开放源代码和跨平台的.NET库,用于记录应用程序中的指标.App Metrics可以在.NET Core或也支持.NET ...
- LeetCode 841:钥匙和房间 Keys and Rooms
题目: 有 N 个房间,开始时你位于 0 号房间.每个房间有不同的号码:0,1,2,...,N-1,并且房间里可能有一些钥匙能使你进入下一个房间. 在形式上,对于每个房间 i 都有一个钥匙列表 ...
- python Condition
import threading # 必须要使用condition的例子 # class XiaoAi(threading.Thread):# def __init__(self, lock):# s ...
- Python机器学习笔记 Grid SearchCV(网格搜索)
在机器学习模型中,需要人工选择的参数称为超参数.比如随机森林中决策树的个数,人工神经网络模型中隐藏层层数和每层的节点个数,正则项中常数大小等等,他们都需要事先指定.超参数选择不恰当,就会出现欠拟合或者 ...
- 何谓SQLSERVER参数嗅探(转载)
大家听到“嗅探”这个词应该会觉得跟黑客肯定有关系吧,使用工具嗅探一下参数,然后截获,脱裤o(∩_∩)o .事实上,我觉得大家太敏感了,其实这篇文章跟数据库安全没有什么关系,实际上跟数据库性能调优有关相 ...
- Java面试题:Java中的集合及其继承关系
关于集合的体系是每个人都应该烂熟于心的,尤其是对我们经常使用的List,Map的原理更该如此.这里我们看这张图即可: 1.List.Set.Map是否继承自Collection接口? List.Set ...