C++ 快速回顾(五)

发布于:2025-07-01 ⋅ 阅读:(20) ⋅ 点赞:(0)

前言

用于快速回顾之前遗漏或者补充C++知识

一、Dll和Lib的区别

静态库(LIB)在编译时链接,代码被复制到可执行文件中。
动态库(DLL)在运行时链接,可执行文件只包含对 DLL 中函数的引用。

区别

文件分布​​:
静态库:可执行文件独立,不需要额外的库文件。
动态库:可执行文件需要依赖 DLL 文件。
​​更新和维护​​:
静态库:更新库需要重新编译程序。
动态库:更新 DLL 可以独立进行(但要保持接口兼容),程序无需重新编译。
​​内存占用​​:
静态库:每个使用库的程序都会在内存中有自己的一份库代码拷贝。
动态库:多个程序可以共享内存中的同一份 DLL 代码。
​​加载​​:
静态库:在程序启动时,代码已经被加载。
动态库:可以在程序启动时加载(隐式链接),也可以在程序运行时按需加载(显式链接,使用 LoadLibrary 和 GetProcAddress 函数)。

在开发中使用

静态库(LIB)的使用​​:
在项目配置中,需要指定静态库的路径和库文件名。链接时,链接器会将库中的代码直接整合到可执行文件中。
​​动态库(DLL)的使用​​:
需要两个文件:DLL 文件和导入库(.lib)。在链接时,使用导入库来解析符号,但代码不会复制到可执行文件。运行时,DLL 文件必须放在可执行文件的目录或系统路径中。

如何选择​​:
如果需要减少可执行文件的大小,方便更新,或者多个程序共享库代码,则使用 DLL。
如果希望程序独立运行,不依赖外部文件,则使用静态库。

在这里插入图片描述

二、封装并使用C++库

题外话:防止头文件被重复包含的两种方式
1.#pragma once
2.宏定义包裹,如下:

#ifndef INTERFACE_H
#define INTERFACE_H

//TODO:

#endif // !INTERFACE_H

1.封装库

定义导出宏

#define TESTCPP_API __declspec(dllexport)

整体的头文件如下,IInterface这个类加了导出宏就可以被导出给外界使用
在这里插入图片描述
具体的实现如下,FHello这个类没有加导出宏,我们只在内部使用导出后的DLL无法直接使用此类
如下代码就是将FHello这个类作为内部实现,然后提供CreateInterface 这个接口给外界调用,返回的是内部定义的类
在这里插入图片描述
在项目属性中分别选择Dll和Lib导出
在这里插入图片描述
会生成以下这些文件
在这里插入图片描述
我们最后实际上使用的只有如下这几个文件,头文件是方便我们调用函数等查看使用,具体的实现都在dll或者lib中了
在这里插入图片描述

2.使用库

有了上面导出的库文件,我们可以来使用了
我们新建控制台项目,导入之前生成的库文件到自定义的目录中
在这里插入图片描述
可以看到我们可以正常包含我们实现的内容

#include "dlllib/Interface.h"
#include <iostream>

int main()
{
	IInterface* Interface = IInterface::CreateInterface();
	Interface->Init();
	printf(Interface->GetName());
	Interface->Destroy();

	system("pause");
	return 0;
}

但是这时候运行却运行不起来
我们需要根据需要设置此路径
在这里插入图片描述
此处有两种方式可以选择
第一种是直接在设置处设置即可
在这里插入图片描述
第二种是在代码中设置
在这里插入图片描述
在生成前把库拷贝到对应生成目录之下
xcopy /e /r /y $(ProjectDir)dlllib $(OutDir)
在这里插入图片描述
在这里插入图片描述

三、封装并使用C库

1.封装库

使用c来封装库时要注意

#ifdef __cplusplus
extern "C"
{
#endif

同时注意函数要使用 ** __stdcall** 写在要导出的函数前面,这个是函数压栈依次进行的标识

在这里插入图片描述
下面是具体的函数实现
在这里插入图片描述

2.使用库

使用的方式同上C++使用类库
可以看到只有CTEST_API导出宏的函数可以正常进行使用,不然会在运行时报错!!!
在这里插入图片描述