环境
Visual Studio 2022
代码编辑
创建工程hello
hello.cpp
#include <iostream>
#include "hello.h"// 定义函数原型,该函数将在DLL中被导出
extern "C" __declspec(dllexport) int Add(int a, int b) {std::cout << "The value of a is: " << a << std::endl;std::cout << "The value of b is: " << b << std::endl;return a + b;
}
hello.h
#pragma once
#ifdef MYLIBRARY_EXPORTS
#define MYLIBRARY_API __declspec(dllexport)
#else
#define MYLIBRARY_API __declspec(dllimport)
#endif
#define FNEGZHUANGCPP_API __declspec(dllexport)extern "C" FNEGZHUANGCPP_API int Add(int a, int b);右键-》属性
然后将dll和lib都选择
右键-》生成
在工程的第一层级的Debug 里面可以找到编译的库
找到dll和.lib文件,放到一个自己重新建立的独立的文件夹,并且将.h文件放置在一起,就可以给其他程序使用了
使用自己创建的库
现在重新创建一个工程,添加.cpp文件
#include<iostream>
#include "001/hello.h"
#pragma comment(lib,"hello.lib")
int main()
{std::cout << "Hello, World!" << std::endl;Add(1,2);return 0;}
将前面准备的文件夹放到新工程的这个目录下
添加库的路径
点击开始执行,运行成功!!!
动态库dll和静态库lib 的区别
在 Windows 系统中,DLL(Dynamic Link Library,动态链接库)和 LIB(Library,静态库)都是用于代码复用和模块化编程的重要机制,但它们在多个方面存在区别,以下是详细介绍:
- 概念与原理
DLL:是一个包含可由多个程序同时使用的代码和数据的库。DLL 中的函数和数据在运行时才被加载到内存中,并且多个应用程序可以共享同一个 DLL 在内存中的副本,从而节省系统资源。当一个程序需要使用 DLL 中的函数时,操作系统会将 DLL 加载到进程的地址空间,并根据需要调用其中的函数。
LIB:分为静态库和导入库两种类型。静态库是在编译时将库中的代码和数据直接复制到可执行文件中的库文件,使得可执行文件在运行时无需依赖外部的库文件即可独立运行。而导入库则是用于在链接阶段提供关于 DLL 中函数和符号的信息,帮助编译器生成正确的可执行文件,以便在运行时能够正确地加载和调用 DLL 中的函数。 - 生成与使用方式
DLL:通常使用特定的开发工具(如 Visual C++、Delphi 等)创建,在项目中定义好要导出的函数和变量,并进行相应的编译和链接操作,生成 DLL 文件。使用时,需要在应用程序中通过动态加载的方式(如使用 LoadLibrary 函数等)将 DLL 加载到内存中,然后获取函数指针并调用其中的函数。
LIB:静态库的生成也是通过开发工具将多个目标文件组合而成,在编译可执行文件时,通过在项目设置中指定静态库的路径和名称,编译器会将静态库中的代码和数据整合到可执行文件中。对于导入库,它一般是与相应的 DLL 文件一同生成的,在链接可执行文件时,需要同时指定导入库和 DLL 文件,以便正确地建立可执行文件与 DLL 之间的链接关系。 - 内存管理与共享
DLL:由于多个应用程序可以共享同一个 DLL 在内存中的副本,因此在内存管理上具有一定的优势,可以有效地节省系统内存资源。当多个程序同时使用同一个 DLL 时,只有一份 DLL 代码会被加载到内存中,各个程序通过不同的地址空间来访问和使用其中的函数和数据。
LIB:静态库在编译时就将所有的代码和数据复制到了可执行文件中,因此每个使用该静态库的可执行文件都有一份独立的库代码副本,这可能会导致在多个应用程序使用相同静态库时,内存中存在多份相同的代码,占用较多的内存空间。 - 可维护性与更新
DLL:具有较好的可维护性和更新灵活性。当 DLL 中的代码需要修改或更新时,只需要替换相应的 DLL 文件,而无需重新编译所有使用该 DLL 的应用程序,只要保持函数的接口不变,应用程序就可以正常运行。这对于大型软件系统中多个应用程序共享的公共功能模块的维护和升级非常方便。
LIB:静态库一旦被链接到可执行文件中,就成为了可执行文件的一部分,若要更新静态库中的代码,就需要重新编译所有使用该静态库的应用程序,否则无法获取到更新后的功能。这在一定程度上增加了维护的难度和成本,尤其是对于大型项目中广泛使用的静态库。 - 调试与部署
DLL:调试相对复杂一些,因为 DLL 是在运行时动态加载的,需要在调试器中正确设置相关的调试选项,以便能够跟踪到 DLL 中的代码执行情况。在部署时,除了要确保应用程序能够正确找到 DLL 文件外,还需要注意 DLL 的版本兼容性和依赖关系,以避免出现因 DLL 版本不匹配或依赖项缺失而导致的运行时错误。
LIB:静态库的调试相对简单,因为其代码已经整合到可执行文件中,可以直接在可执行文件的调试过程中进行调试。在部署时,只需要将可执行文件复制到目标机器上即可,无需额外考虑库文件的部署问题,因为所有需要的代码都已经包含在可执行文件中。 - 适用场景
DLL:适用于多个应用程序需要共享相同功能模块的情况,如系统级的功能库、插件式的软件架构等。通过使用 DLL,可以有效地减少代码的重复编写和内存的占用,提高软件的可维护性和可扩展性。
LIB:静态库适用于对性能要求较高、不希望依赖外部库文件、或者需要将所有代码整合到一个可执行文件中的场景,如一些小型的、独立的工具软件等。在某些情况下,对于一些不经常更新的基础功能库,使用静态库也可以简化部署和维护过程。