DLL介绍

DLL(动态链接库,Dynamic Link Library)是一种可执行文件,它包含可以在其他程序中调用的函数和数据。他是Windows操作系统中的一个重要概念,用于代码共享和模块化。

特点

  • 代码共享:多个程序可以同时使用同一个DLL文件,而不需要将其代码编译到每个程序中。这样可以节省磁盘空间和内存,并且可以简化程序的更新和维护。
  • 运行时链接:与静态链接库(.lib文件)不同,DLL不是在编译时链接到程序中的,而是在程序运行时链接。这意味着,如果更新了DLL,使用该DLL的程序可以在不重新编译的情况下直接使用新版本。
  • 多语言支持:DLL可以由不同的语言编写,例如C,C++,Delphi等,只要它们遵循一定的调用约定。
  • 可拓展性:应用程序可以通过加载和卸载DLL来动态地增加或减少功能。
  • 资源共享:DLL在内存中只有一个实例,所有使用它的应用程序都共享这个实例,从而节约了资源。

生成DLL

新建dll项目

新建项目-选择“win32控制台应用程序”

接着在弹出框中选择dll和空项目



完成后得到空项目的目录结构,创建DLL1.hDLL1.cpp两个文件

书写代码

  • DLL1.cpp中实现两个数求和与求差的接口:
int sum(int a, int b){
return a + b;
}
int sub(int a, int b){
return a - b;
}
  • DLL1.h中声明函数:
int sum(int a, int b);
int sub(int a, int b);
  • 为了能在dll中使用,还需要给函数加上前缀:extern "C" __declspec(dllexport)

    • 其中_declspec(dllexport)的意思是指定需要到出到dll的目标(用于生成dll)

    • extern "C"表示将C语言程序导出为DLL

extern "C" __declspec(dllexport) int sum(int a, int b);
extern "C" __declspec(dllexport) int sub(int a, int b);

也可以使用宏定义,使代码更具可读性

#define SumAndSub_API __declspec(dllexport)

extern "C" SumAndSub_API int sum(int a, int b);
extern "C" SumAndSub_API int sub(int a, int b);

生成DLL

.h.cpp中添加代码之后,右击项目选择“生成”



生成成功后,在项目Debug文件夹下即可找到生成的dll文件



到这DLL的封装算是完成了

调用DLL

隐式调用

首先需要重新创建一个空项目来调用测试:

创建完成之后,还需引入三个文件即前面生成的DLL1.dllDLL1.lib以及项目DLL1.h文件

其中DLL1.dll需要放在当前项目的Debug目录下,其他两个在属性中配置路径即可(DLL1.lib还需添加依赖项)

右击项目-选择属性

选择VC++目录

其中“包含目录” 添加.h文件所在文件夹

“库目录”添加.lib所在目录

添加完成后如图:

然后在链接器-输入选项中添加依赖项

完成后应用属性保存,然后将DLL文件复制到当前项目的Debug目录下

下面新建一个test.cpp来测试下是否能够成功调用到DLL

#include "iostream"
#include "DLL1.h"
using namespace std; int main(){
cout << sum(2, 5) << endl;
cout << sub(5, 2) << endl;
system("pause");
return 0;
}

成功调用到DLL

显式调用

显式调用中又包含静态调用动态调用

静态显式调用

  • 静态调用:.lib文件包含了函数代码本身,在编译时直接将代码加入程序当中,称为静态链接库(static link library)。静态调用使用静态链接库,链接器从静态链接库LIB获取所有被引用函数,并将库同代码一起放到可执行文件中。

先创建一个新的空项目,创建完成后添加一个.cpp源文件并写入简单的主函数

int main(){

}

右击项目选择-生成(生成Debug目录)

DLL1.dll放到当前项目的Debug目录下

创建.cpp源文件通过以下代码进行静态调用

#include "iostream"
using namespace std;
#pragma comment(lib, "D:\\Code\\C++\\dll\\DLL1\\Debug\\DLL1.lib")
// dll中封装的函数
extern "C" __declspec(dllimport) int sum(int, int);
extern "C" __declspec(dllimport) int sub(int, int); int main(){
cout << sum(2, 5) << endl;
cout << sub(5, 2) << endl;
system("pause");
return 0;
}

其中#pragma comment(lib, "D:\\Code\\C++\\dll\\DLL1\\Debug\\DLL1.lib")

表示链接DLL1.lib这个库,与在项目属性中的“VC++目录”中的“库目录”添加目录以及链接器-输入添加依赖性操作是等价的(一个显式一个隐式的区别)。

动态显式调用

  • 动态调用:.lib文件包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供,称为动态链接库(dynamic link library)。动态调用使用动态链接库,可执行模块(.dll文件或.exe文件)本身不包含它调用的DLL函数的代码,仅包含在运行时定位DLL函数的代码所需的信息,在程序运行时能够找到并链接到正确的DLL文件和函数。(这些信息通常包括函数名、参数类型等,足以让操作系统在运行时解析并调用正确的函数。)

同样创建项目后先生成Debug目录

生成之后将DLL1.dll放入Debug目录中

通过如下方式进行动态调用

  • 首先通过LoadLibrary()函数来载入指定的dll文件,加载到程序的内存中(DLL没有自己的内存)
  • GetProcAddress()函数检索指定dll文件输出库函数地址,通过函数指针typedef int(*func)(int a, int b);来装载函数并使用。
  • FreeLibrary()释放dll所占的空间。
#include "iostream"
#include "windows.h"
using namespace std; typedef int(*func)(int a, int b); int main(){
// 动态加载dll
HMODULE hModule = LoadLibrary("DLL1.dll");
if (!hModule){
cout << "Error!" << endl;
}
// 装载函数
func sum = func(GetProcAddress(hModule, "sum"));
func sub = func(GetProcAddress(hModule, "sub")); if (sum != NULL){
cout << sum(5, 2) << endl;
}
if (sub != NULL){
cout << sub(5, 2) << endl;
} // 释放
FreeLibrary(hModule);
system("pause");
return 0;
}

注意:动态调用方式通常是只有.dll文件,而缺少.h.lib文件时使用,当三个文件都齐全时,应采用更加简单方便的隐式调用

VS(visual studio) C++ 封装dll,以及其隐式调用与显式调用(静态\动态)的更多相关文章

  1. Visual Studio 提示某个dll文件(已在Microsoft Visual Studio 外对该文件进行了修改,是否重新加载它)

    如题: Visual Studio 提示某个dll文件(已在Microsoft Visual Studio 外对该文件进行了修改,是否重新加载它) 如果选择“是”,那恭喜你,第二次生成的时候,引用这个 ...

  2. Visual Studio 调用 Delphi DLL 会退出的解决方案

    新写了一个 Delphi 的 dll 供 C# 程序调用,却发现在使用 Visual Studio 2012 进行调试时,程序会在调用后自动退出. 经过对比,只需要将工程属性中“调试”一页下的“启用 ...

  3. Visual Studio 创建封装自己的代码段(C#)

    https://www.cnblogs.com/awaTangjay/p/6644952.html 1.打开vs2012--工具--代码段管理器 2.进入代码管理器之后,语言选择Visual C#,然 ...

  4. Visual Studio快速封装字段方法

    在面向对象的编程中我们常常要将各个字段封装为属性,但是当字段多的时候往往这个重复的操作会大大降低我们的开发效率,那么如何才能快速的封装字段呢?下面就给大家2个解决方法: 1.使用封装字段方法: 选中字 ...

  5. simplest_dll 最简dll的创建与隐式调用(显式调用太麻烦,个人不建议使用)

    首先需要有个头文件,名字随便写  假设test.h //test.h #ifndef _TEST_H #define _TEST_H #ifdef TEST_EXPORTS //通过宏定义控制是输入还 ...

  6. Visual Studio 创建和使用dll的方法

    DLL是一个包含可由多个程序同时使用的代码和数据的库. DLL文件就是把一些函数导出来,然后在新程序中进行复用的过程. 第一部分:使用Visual Studio 2010进行DLL的制作 生成方法一: ...

  7. Visual Studio 写自己的动态链接库(DLL)

    有些时候,我们想写自己的函数库以避免重复写代码,此文介绍如何使用Visual Studio编写自己的动态链接库. 0,实验环境说明: 集成开发环境:Visual Studio 10.0 操作系统: W ...

  8. Visual studio 配置

    解决方案 一个解决方案的文件结构: .sln        项目目录         debug   release 其中,debug与release放置最终生成的dll或exe,项目目录下包含 头文 ...

  9. 【译】Visual Studio 15 预览版更新说明

    序:恰逢Build2016大会召开,微软发布了VS2015的update2更新包和VS2016预览版.本人正在提升英文水平中,于是在这里对VS2016预览版的官方文档进行了部分翻译.因为VS有些功能使 ...

  10. 微软推出ASP.NET Core 2.0,并支持更新Visual Studio 2017

    微软推出ASP.NET Core 2.0的一般可用性,并发布.NET Core 2.0.该公司还推出了其旗舰集成开发环境(IDE)的更新:Visual Studio 2017版本15.3和Visual ...

随机推荐

  1. C# 泛型单例工厂

    核心代码,线程安全 class SingletonFactory<T> where T : new() { private static T uniqueInstance; private ...

  2. 一文全懂:独立冗余磁盘阵列(RAID)

    独立冗余磁盘阵列,也就是大家常说的RAID,英文全称是:Redundant Array of Independent Disks,使用该技术,可以大幅提高硬盘设备的 IO 读写速度,还存在数种数据冗余 ...

  3. Python 实时获取任务请求对应的Nginx日志

    需求描述 项目需求测试过程中,需要向Nginx服务器发送一些用例请求,然后查看对应的Nginx日志,判断是否存在特征内容,来判断任务是否执行成功.为了提升效率,需要将这一过程实现自动化. 实践环境 P ...

  4. .NET TCP、UDP、Socket、WebSocket

    做.NET应用开发肯定会用到网络通信,而进程间通信是客户端开发使用频率较高的场景. 进程间通信方式主要有命名管道.消息队列.共享内存.Socket通信,个人使用最多的是Sokcet相关. 而Socke ...

  5. 写写Redis十大类型GEO(地理空间)的常用命令

    又是一个用于处理sql性能的类型,这个类型的核心思想就是把三维的地球变成二维的坐标,再将二维的坐标换成一维的点块,最后将一维的点块转化成base32编码 类型就是zset, 在shell的启动命令后加 ...

  6. Segment-anything学习到微调系列_SAM初步了解

    Segment-anything学习到微调系列_SAM初步了解 前言 本系列文章是博主在工作中使用SAM模型时的学习笔记,包含三部分: SAM初步理解,简单介绍模型框架,不涉及细节和代码 SAM细节理 ...

  7. 【Mybatis】07 万用Map & 模糊查询细节

    这应该算一个补充点 在尚硅谷的Java笔记资料有专门的一起万用Map讲解 参考自:https://www.bilibili.com/video/BV1NE411Q7Nx?p=5 万用Map 我们可以使 ...

  8. 【C】Re02

    一.命令行参数 #include <stdio.h> /** * 运行执行程序的命令携带 一些附加参数,传递给程序执行 * @param argc 命令行参数的个数 * @param ar ...

  9. ubuntu:通过缺失的系统lib库文件查找所需要安装的package——根据lib文件查找所属的package包——命令:sudo apt-file search

    参考: 使用apt-file,根据文件查找所需安装的软件包 ======================================= 使用 apt-file 命令可以通过lib文件名查找其所属的 ...

  10. 【转载】python的魔法方法———A Guide to Python's Magic Methods

    原文地址: https://rszalski.github.io/magicmethods/ ===================================================== ...