3、CMake语法:制作和使用动态库和静态库
动态库和静态库
- 1 动态库和静态库简介
- 1.1 静态库
- 静态库文件类型
- .lib 文件
- .pdb 文件
- 1.2 动态库
- 动态库文件类型
- 1.3 总结
- 2. 制作和使用静态库
- 2.1 CMake
- 指定输出的路径
- 2.2 VS
- 利用第三方库编译静态库
- 2.3 使用静态库
- CMake链接静态库
- VS链接静态库
- 3. 制作和使用动态库
- 3.1 CMake
- 指定输出的路径
- 3.2 VS创建
- 3.3 使用动态库
- CMake
- 语法
- 应用
- 链接第三方动态库
- VS2019
1 动态库和静态库简介
编译平台:Winsows系统和VS2019,语言:C++
1.1 静态库
在编译时,静态库会被完整地链接到可执行文件中。也就是说,编译器会将静态库中的代码复制到生成的可执行文件里。这使得可执行文件在运行时不再依赖该静态库,即使静态库文件被删除或移动,可执行文件依然能够正常运行。
由于静态库的代码会被完整地复制到可执行文件中,所以会导致可执行文件的体积显著增大。如果多个可执行文件都使用了同一个静态库,那么每个可执行文件中都会包含该静态库的副本,造成磁盘空间的浪费。
每个使用静态库的程序都有一份库代码的副本,这会导致内存中存在大量重复的代码,增加了内存的占用。
如果静态库的代码发生了更新,那么使用该静态库的所有程序都需要重新编译和链接,否则无法使用新的库功能或修复的问题。这在库更新频繁的情况下会带来很大的工作量。
静态链接的可执行文件不依赖外部的库文件,因此可以在没有安装相应静态库的环境中运行,具有较好的独立性。
由于在编译时需要将静态库的代码复制到可执行文件中,所以编译过程相对较慢,尤其是当静态库较大时。
- 静态库适用场景
对程序的独立性要求较高,不希望依赖外部环境;或者库的更新频率较低,不需要频繁更新库代码的情况。例如一些嵌入式系统开发,由于运行环境相对固定,使用静态库可以确保程序的稳定性。
例如,一个大型项目可以将图形处理、网络通信等功能分别封装成不同的静态库。
静态库文件类型
.lib 文件
.lib 文件是静态链接库文件,在 Windows 平台的开发中经常使用。它有两种主要类型:
- 静态库(Static Library):包含了实际的代码和数据,当使用静态库进行链接时,链接器会将 .lib 文件中的代码和数据复制到最终的可执行文件中。这种方式使得可执行文件独立于外部库,不依赖于运行时环境中的库文件。例如,你在开发一个 Windows 控制台程序时使用了某个数学计算的静态库,链接后,这个静态库的代码就成为了你可执行文件的一部分。
- 导入库(Import Library):用于动态链接库(DLL)的链接过程。导入库并不包含 DLL 的实际代码,而是包含了 DLL 中导出函数和变量的符号信息以及它们的地址。在链接使用 DLL 的程序时,链接器会根据导入库中的信息在可执行文件中记录对 DLL 中函数和变量的引用,当程序运行时,操作系统会根据这些引用信息加载相应的 DLL。
.pdb 文件
.pdb 是程序数据库(Program Database)文件,它是 Visual Studio 等开发工具生成的一种文件,用于存储调试信息。
- 调试支持:在调试程序时,调试器(如 Visual Studio 的调试器)会使用 .pdb 文件中的信息来关联源代码和内存中的机器码。这样,当你在调试器中设置断点、查看变量值等操作时,调试器可以准确地定位到源代码中的具体位置,显示变量的名称和值,帮助你快速定位和解决程序中的问题。
- 符号信息:.pdb 文件包含了程序中所有符号(如函数名、变量名等)的详细信息,以及它们在内存中的地址和偏移量。这些信息对于调试和分析程序的运行状态非常有用。
.pdb 文件和 .lib 文件是相互独立的。.lib 文件主要用于程序的链接过程,而 .pdb 文件主要用于程序的调试过程。在发布程序时,通常不需要将 .pdb 文件一同发布,因为它主要是为开发和调试阶段服务的;而 .lib 文件(如果是静态库)会成为可执行文件的一部分,或者(如果是导入库)用于引导程序加载动态库。
1.2 动态库
动态库在编译时并不会被链接到可执行文件中,而是在程序运行时才会被加载。可执行文件中仅包含对动态库的引用信息,当程序启动时,操作系统会根据这些引用信息去查找并加载相应的动态库。
动态库的代码不会被复制到可执行文件中,可执行文件只包含对动态库的引用,因此可执行文件的体积相对较小。而且多个程序可以共享同一个动态库的副本,节省了磁盘空间。
多个程序可以共享同一个动态库的实例,在内存中只需要加载一份动态库代码,从而减少了内存的占用。
动态库的更新相对方便,只需要替换动态库文件即可。使用该动态库的程序在下次运行时会自动加载新的库文件,无需重新编译。
动态链接的可执行文件依赖于系统中安装的动态库文件。如果目标系统中缺少相应的动态库,或者动态库的版本不兼容,程序可能无法正常运行。
动态库的编译过程只需要生成库文件,而不需要将库代码复制到可执行文件中,因此编译速度相对较快。
- 动态库适用场景
多个程序需要共享相同的功能,或者库的更新比较频繁的情况。例如操作系统中的图形库、网络库等,多个应用程序可以共享这些动态库,同时库的更新也可以方便地推送给所有使用该库的程序。
动态库文件类型
- .dll 文件:这是动态库的主要文件,包含了可被多个程序同时使用的代码和数据,在运行时被加载到内存中供程序调用。
- .lib 文件:这里的.lib 文件是导入库文件,用于在链接阶段告诉链接器动态库中导出函数和变量的符号信息以及它们的地址,并非静态库中的那种包含实际代码和数据的.lib 文件。
- .pdb 文件:程序数据库文件,存储着调试信息,用于在调试过程中帮助开发人员将源代码与运行时的机器码关联起来,方便查看变量值、定位代码位置等。
1.3 总结
通常情况下,发布动态库时,.dll 文件是必须的,而.lib 文件和.pdb 文件是否一同发布,取决于具体需求。如果希望其他开发人员在链接时使用该动态库,就需要提供导入库.lib 文件;.pdb 文件主要用于开发和调试阶段,一般在发布给最终用户的产品中不会包含,但在内部测试或给开发人员使用时可能会提供。
- 动态链接库是更推荐的方式,因为它允许更精确的控制和管理链接库的依赖,特别是在大型项目中,它能够避免全局设置可能带来的问题。
- 静态库虽然简单,但在复杂的项目中可能会导致意外的问题,通常适用于简单的项目或临时设置。
2. 制作和使用静态库
配搭代码
2.1 CMake
在cmake中,如果要制作静态库,需要使用的命令如下:
add_library(库名称 STATIC 源文件1 [源文件2] ...)
在Linux中,静态库名字分为三部分:lib+库名字+.a,此处只需要指定出库的名字就可以了,另外两部分在生成该文件的时候会自动填充。
在 Windows 系统里,静态库文件的扩展名一般是 .lib。例如,若有一个用于处理数学计算的静态库,可能会被命名为 mathlib.lib 。第三方静态库:如OpenSSL 静态库
- 实例:有一个目录,需要将src目录中的源文件编译成静态库,然后再使用:
.
├── build
├── CMakeLists.txt
├── include # 头文件目录
│ └── head.h
├── main.cpp # 用于测试的源文件
└── src # 源文件目录├── add.cpp├── div.cpp├── mult.cpp└── sub.cpp
根据上面的目录结构,可以这样编写CMakeLists.txt文件:
cmake_minimum_required(VERSION 3.10)
project(CALC)
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
add_library(calc STATIC ${SRC_LIST})
这样最终就会生成对应的静态库文件。
生成后用VS对项目进行生成,得到calc.lib文件。
指定输出的路径
由于在Linux下生成的静态库默认不具有可执行权限,所以在指定静态库生成的路径的时候就不能使用EXECUTABLE_OUTPUT_PATH宏了,而应该使用LIBRARY_OUTPUT_PATH,这个宏对应静态库文件和动态库文件都适用。
cmake_minimum_required(VERSION 3.0)
project(CALC)
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
# 设置动态库/静态库生成路径
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
# 生成动态库
#add_library(calc SHARED ${SRC_LIST})
# 生成静态库
add_library(calc STATIC ${SRC_LIST})
2.2 VS
创建步骤:
-
创建静态库项目
-
添加静态库代码:添加头文件和源文件,不需要main.cpp的执行文件(最好采用namespace来进行区分函数或者类)
-
配置静态库项目
-
生成静态库:生成->生成解决方案;生成的文件位于配置编译方式的文件夹中
利用第三方库编译静态库
- 不需要链接器,因为不动态调用库。静态库的使用是将源代码拷贝到项目中进行运行。
相当于拷贝进入项目一段代码。
与函数创建静态库相同,不同的是需要在项目属性中配置《包含目录》和《库目录》,不用设置链接器的“输入”。
Note:在编译前要确定第三方库是X86还是64位编译。
2.3 使用静态库
CMake链接静态库
文件目录:
$ tree
.
├── build
├── CMakeLists.txt
├── include
│ └── head.h
├── lib
│ └── libcalc.a # 制作出的静态库的名字,源文件已经删除,不需要了,生成了静态库
└── src└── main.cpp4 directories, 4 files
在cmake中,链接静态库的命令如下:
# 用于设置全局链接库,这些库会链接到之后定义的所有目标上。
link_libraries(<static lib> [<static lib>...])
- 参数1:指定出要链接的静态库的名字,可以是全名 libxxx.a;也可以是掐头(lib)去尾(.a)之后的名字 xxx
- 参数2-N:要链接的其它静态库的名字,多个静态库之间用空格隔开
如果该静态库不是系统提供的(自己制作或者使用第三方提供的静态库)可能出现静态库找不到的情况,此时可以将静态库的路径也指定出来:
link_directories(<lib path>) #多个静态库路径之间用空格隔开
CMakeLists.txt文件内容如下:
cmake_minimum_required(VERSION 3.0)
project(CALC)
# 搜索指定目录下源文件
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) #执行的程序文件
# 包含头文件路径
include_directories(${PROJECT_SOURCE_DIR}/include)
# 包含静态库路径
link_directories(${PROJECT_SOURCE_DIR}/lib)
# 链接静态库
link_libraries(calc)
add_executable(app ${SRC_LIST})
VS链接静态库
-
方法1
最直接的方法是将.h和.cpp文件直接放入项目中运行。 -
方法2
需要文件:.h头文件和.lib静态库文件
VS2019中使用步骤:- 添加新项目
- 右键项目 → 属性,在其中设置
- 配置属性 → VC++目录 → 包含目录:添加:头文件目录
- 链接器 → 常规 → 附加库目录:添加:静态库所在位置
- 链接器 → 输入 → 附加依赖项:添加:静态库名称
- 编写使用代码
- 设置项目依赖:右键解决方案 → 项目依赖项,选取相对应的静态库
-
采用怎样的编译器来生成的静态库,引用的程序就需要用怎样的编译器编译。如果项目中或者静态库采用了第三方库,那么项目必须配置第三方库的信息。
3. 制作和使用动态库
3.1 CMake
在cmake中,如果要制作动态库,需要使用的命令如下:
add_library(库名称 SHARED 源文件1 [源文件2] ...)
- 在Linux中,动态库名字分为三部分:lib+库名字+.so.
- 在windows中,动态库的文件后缀为.dll和.lib
根据上面的目录结构,可以这样编写CMakeLists.txt文件:
cmake_minimum_required(VERSION 3.0)
project(CALC)
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
add_library(calc SHARED ${SRC_LIST})
在Linux中,这样最终就会生成对应的动态库文件libcalc.so。在windows中,还需要编译器进一步编译,生成解决方案。
指定输出的路径
对于生成的库文件来说和可执行程序一样都可以指定输出路径。由于在Linux下生成的动态库默认是有执行权限的,所以可以按照生成可执行程序的方式去指定它生成的目录:
cmake_minimum_required(VERSION 3.0)
project(CALC)
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
# 设置动态库生成路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
add_library(calc SHARED ${SRC_LIST})
- 对于这种方式来说,其实就是通过set命令给EXECUTABLE_OUTPUT_PATH宏设置了一个路径,这个路径就是可执行文件生成的路径。
3.2 VS创建
创建步骤:
- 选择动态链接库项目进行创建
- 添加.h和.cpp文件
- 点击项目,然后生成。此时只会生成.dll文件而没有.lib引导文件,需要添加宏
// DLL导出宏
#ifdef XXXLIB_EXPORTS
#define XXX_API __declspec(dllexport)
#else
#define XXX_API __declspec(dllimport)
#endif
函数则在函数前添加 XXX_API,如果时类则在class后和类名前添加XXX_API。
-
配置解决平台X86/X64都可以,但是这个导出的DLL,用户引用的时候尽量和导出时的DLL平台一致
-
然后点击解决方案,进行生成即可。其中三类文件有用:.h/.dll/.lib。
3.3 使用动态库
在程序编写过程中,除了在项目中引入静态库,好多时候也会使用一些标准的或者第三方提供的一些动态库,关于动态库的制作、使用以及在内存中的加载方式和静态库都是不同的。
CMake
语法
在cmake中链接动态库的命令如下:
target_link_libraries(<target> <PRIVATE|PUBLIC|INTERFACE> <item>... [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
用于指定一个目标(如可执行文件或库)在编译时需要链接哪些库。它支持指定库的名称、路径以及链接库的顺序。
target_link_libraries(A B C)
target_link_libraries(D A)
动态库的链接具有传递性,如果动态库 A 链接了动态库B、C,动态库D链接了动态库A,此时动态库D相当于也链接了动态库B、C,并可以使用动态库B、C中定义的方法。
- target:指定要加载的库的文件的名字
该文件可能是一个源文件
该文件可能是一个动态库/静态库文件
该文件可能是一个可执行文件 - PRIVATE|PUBLIC|INTERFACE:动态库的访问权限,默认为PUBLIC
如果各个动态库之间没有依赖关系,无需做任何设置,三者没有没有区别,一般无需指定,使用默认的 PUBLIC 即可。- PUBLIC:在public后面的库会被Link到前面的target中,并且里面的符号也会被导出,提供给第三方使用。
- PRIVATE:在private后面的库仅被link到前面的target中,并且终结掉,第三方不能感知你调了啥库
- INTERFACE:在interface后面引入的库不会被链接到前面的target中,只会导出符号(不清楚函数属于哪个库,)。
应用
动态库的链接和静态库是完全不同的:
- 静态库会在生成可执行程序的链接阶段被打包到可执行程序中,所以可执行程序启动,静态库就被加载到内存中了。
- 动态库在生成可执行程序的链接阶段不会被打包到可执行程序中,当可执行程序被启动并且调用了动态库中的函数的时候,动态库才会被加载到内存
因此,在cmake中指定要链接的动态库的时候,应该将命令写到生成了可执行文件之后:
cmake_minimum_required(VERSION 3.0)
project(TEST)
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
# 添加并指定最终生成的可执行程序名
add_executable(app ${SRC_LIST})
# 指定可执行程序要链接的动态库名字
target_link_libraries(app pthread)
- app: 对应的是最终生成的可执行程序的名字
- pthread:这是可执行程序要加载的动态库,这个库是系统提供的线程库,全名为libpthread.so,在指定的时候一般会掐头(lib)去尾(.so)。
链接第三方动态库
生成了一个动态库,对应的目录结构如下:
$ tree
.
├── build
├── CMakeLists.txt
├── include
│ └── head.h # 动态库对应的头文件
├── lib
│ └── libcalc.so # 自己制作的动态库文件
└── main.cpp # 测试用的源文件3 directories, 4 files
假设在测试文件main.cpp中既使用了自己制作的动态库libcalc.so又使用了系统提供的线程库,此时CMakeLists.txt文件可以这样写:
cmake_minimum_required(VERSION 3.0)
project(TEST)
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
include_directories(${PROJECT_SOURCE_DIR}/include)
add_executable(app ${SRC_LIST})
target_link_libraries(app pthread calc)
- 在第六行中,pthread、calc都是可执行程序app要链接的动态库的名字。当可执行程序app生成之后并执行该文件,会提示有如下错误信息:
$ ./app
./app: error while loading shared libraries: libcalc.so: cannot open shared object file: No such file or directory
这是因为可执行程序启动之后,去加载calc这个动态库,但是不知道这个动态库被放到了什么位置,所以就加载失败了。在 CMake 中可以在生成可执行程序之前,通过命令指定出要链接的动态库的位置,指定静态库位置使用的也是这个命令:
link_directories(path)
修改之后的CMakeLists.txt文件应该是这样的:
cmake_minimum_required(VERSION 3.0)
project(TEST)
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
# 指定源文件或者动态库对应的头文件路径
include_directories(${PROJECT_SOURCE_DIR}/include)
# 指定要链接的动态库的路径
link_directories(${PROJECT_SOURCE_DIR}/lib)
# 添加并生成一个可执行程序
add_executable(app ${SRC_LIST})
# 指定要链接的动态库
target_link_libraries(app pthread calc)
VS2019
在项目中配置:
右键项目 → 属性
- 配置属性 → VC++目录 → 包含目录:头文件位置
- 链接器 → 常规 → 附加库目录:lib文件位置
- 链接器 → 输入 → 附加依赖项:.lib文件名称
部署动态库:
将.dll复制到以下任一位置:
- 项目的运行程序目录下
- 系统PATH包含的目录
- 与可执行文件相同的目录
设置项目依赖:右键解决方案 → 项目依赖项。
生成解决方案并运行
相关文章:
3、CMake语法:制作和使用动态库和静态库
动态库和静态库 1 动态库和静态库简介1.1 静态库静态库文件类型.lib 文件.pdb 文件 1.2 动态库动态库文件类型 1.3 总结 2. 制作和使用静态库2.1 CMake指定输出的路径 2.2 VS利用第三方库编译静态库 2.3 使用静态库CMake链接静态库VS链接静态库 3. 制作和使用动态库3.1 CMake指…...
使用双端队列deque模拟栈stack
使用双端队列deque模拟栈stack 今天的内容有点简单~ 众所周知🤓👆,栈作为一个先进后出的结构,在计算机的世界确实能够发挥很多的作用。 而我们C祖师爷本贾尼是第一批把这个结构作为实实在在的容器做进std的人~ 那为了更好的了解…...
Spring系列四:AOP切面编程第三部分
🐋AOP-JoinPoint 1.通过JoinPoint可以获取到调用方法的签名 2.其他常用方法 ●代码实现 1.com.zzw.spring.aop.aspectj.SmartAnimalAspect Aspect //表示是一个切面类 Component //会将SmartAnimalAspect注入到容器 public class SmartAnimalAspect {//给Car配置…...
为什么使用ThreadLocal后要调用remove()方法呢?
ThreadLocalMap中包含一个数组,每个节点对应的类名叫Entry,这个类继承WeakReference<ThreadLocal<?>>,entry中有两个属性:key和value。特别需要指出的是key来自于父类中的threadLocal对象。 为了避免内存泄露&#…...
如何在idea 中写spark程序
在 IntelliJ IDEA 中编写 Spark 程序可以通过以下步骤进行: 1. **安装 Scala 插件**:首先确保已经安装了 Scala 插件。在 IntelliJ IDEA 中选择 File -> Settings -> Plugins -> 搜索 Scala -> 安装插件。 2. **创建新项目**:在…...
国产全兼容ADS131E08芯片---LHA7878
LHA787X是一系列多通道同步采样、24位A-∑模数转换器(ADC),内置可编程增益放大器(PGA)、内部基准和振荡器。凭借ADC的宽动态范围、可扩展数据传输速率以及内部故障检测监测计,LHA787X受到工业电源监测和保护以及测试和测量应用的青睐。真正的高阻抗输入支…...
免费LUT网站
FREE LUTs | Color Lookup Tables - Presetpro.com...
ICH CTD中ISS的关键内容与作用
1. ISS在ICH CTD中的定位 1.1 模块2与模块5的分工 1.1.1 模块2:整体总结的全局视角 模块2的2.7.4 ISS对所有临床研究安全性数据整合分析,涵盖I-III期试验,提供药物安全性全局视角,确保其在目标人群中的可接受性。 ISS需与风险控制措施关联,如说明书警示、风险管理计划,…...
Ocelot的应用案例
搭建3个项目,分别是OcelotDemo、ServerApi1和ServerApi2这3个项目。访问都是通过OcelotDemo进行轮训转发。 代码案例链接:https://download.csdn.net/download/ly1h1/90715035 1.架构图 2.解决方案结构 3.步骤一,添加Nuget包 4.步骤二&…...
OpenCV VC编译版本
vc12 Visual Studio 2013 vc14 Visual Studio 2015 vc15 Visual Studio 2017 vc16 Visual Studio 2019 vc17 Visual Studio 2022 opencv支持情况: OpenCV2.4.10 支持 VS2010,VS2012,VS2013 (x64,x86) …...
测试用例介绍
文章目录 一、测试用例基本概念1.1 测试用例基本要素 二、测试用例的设计方法2.1 基于需求的设计方法2.2 等价类2.3 边界值2.4 错误猜测法2.6 场景设计法2.7 因果图2.5 正交排列 三、综合:根据某个场景去设计测试用例(万能公式)四、如何使用F…...
Vue 2 中 Vue 实例对象(vm)的所有核心方法,包含完整示例、使用说明及对比表格
以下是 Vue 2 中 Vue 实例对象(vm)的所有核心方法,包含完整示例、使用说明及对比表格: 1. $mount() 作用:手动挂载 Vue 实例到 DOM 元素 参数: element:DOM 元素或选择器字符串(可…...
大模型的scaling laws:Scaling Laws for Neural Language Models
一、TL;DR Loss与模型size、数据集大小以及用于训练的计算量呈幂律关系其他架构细节,如网络宽度或深度,在较宽范围内影响极小简单的公式可以描述过拟合与模型/数据集大小的依赖关系,以及训练速度与模型大小的依赖关系作用&#x…...
【Docker】使用 jq 管理镜像源
国内访问 Docker Hub 速度较慢,通过配置国内镜像加速器,可显著加快拉取镜像速度。使用 jq 操作 /etc/docker/daemon.json 的 registry-mirrors 字段,可避免手动编辑带来的格式错误,并在添加、替换、删除等场景下保持高效与安全。 …...
青年座谈会的读书汇报
今天,单位组织了一个五四青年座谈会,我们室由于大家都在出差忙之类的,我必须要参加,还要我做一个汇报,我一新来的还没深入到研发工作中,于是决定写了一篇简单的读书笔记,再用deepseek润色一下&a…...
leetcode刷题日记——两数相加
[ 题目描述 ]: [ 思路 ]: 通过两个循环将 l1, l2存储的数字读出,然后求和,再将结果存储链表中由此发了一个问题,结果溢出,如果使用更大的 long 类型,后续不出所料,仍然超出所以只能…...
使用腾讯地图检索地点
最近需求又多了,现在需要使用腾讯地图检索功能,需要经纬度返给商户后端 效果图: 把地图写成组件 现在components创建map/Getpoint.vue 代码如下 <template><div class"getpoint-container"><div><div id&…...
VINS-FUSION:跑通手机录制数据
文章目录 📚简介🚀手机录制数据🚀跑通数据🔧启动rviz🔧启动配置🔧播放rosbag🎯跑通结果 📚简介 利用智能手机的 摄像头IMU 采集数据,并在 VINS-Fusion(视觉惯…...
iView Table 组件跨页选择功能实现文档
iView Table 组件跨页选择功能实现文档 功能概述 实现基于 iView Table 组件的多选功能,支持以下特性: ✅ 跨页数据持久化选择✅ 当前页全选/取消全选✅ 自动同步选中状态显示✅ 分页切换状态保持✅ 高性能大数据量支持 实现方案 技术栈 iView UI 4…...
Spark知识总结
宽窄依赖:父RDD的分区只对应下面子RDD的一个分区,为窄依赖。其余为宽依赖 维度窄依赖宽依赖数据传输无shuffle,本地处理14需shuffle,跨节点传输14并行度高(允许流水线并行)57低(需等…...
window 图形显示驱动-在 WDDM 1.2 中提供无缝状态转换(下)
在不禁用驱动程序的情况下转换到操作系统 有时操作系统遇到不可恢复的错误,必须发出系统 bug 检查。 发生这种情况时,在某些情况下,操作系统必须控制显示器,但无法停止 WDDM 驱动程序。 需要 WDDM 1.2 及更高版本的驱动程序来实现…...
WPF之Label控件详解
文章目录 1. 引言2. Label控件基础2.1 类继承结构2.2 Label类定义 3. Label控件的核心属性3.1 Content属性3.2 Target属性3.3 其他常用属性 4. 标签样式与模板自定义4.1 简单样式设置4.2 使用Style对象4.3 触发器使用4.4 使用ControlTemplate完全自定义 5. Label与表单控件交互…...
STM32 HAL库实现USB虚拟串口
1. 引言 在嵌入式系统开发中,USB 虚拟串口是一种非常实用的功能。它允许 STM32 微控制器通过 USB 接口与计算机进行通信,就像使用传统的串口一样。这种方式不仅简化了硬件设计,还提高了通信的灵活性和稳定性。STM32F407 系列微控制器具有强大…...
第二阶段:基础加强阶段总体介绍
Java语法的学习笔记 下面放复习的文档链接,如果有需要可以前往下载获取,这个仓库还有关于mysql、hadoop、python等的复习部分,并且每个文档有着对应的代码部分。文章作为复习使用,更多代码内容见链接如下: https://gitee.com/zha…...
Callable Future 实现多线程按照顺序上传文件
/** * 异步上传 BiopsyFlow 中的所有视频和音频文件到暂存服务器 */ private List<String> uploadBiopsyFlowFiles(BiopsyFlow biopsyFlow, SyncFile SyncFile) { List<String> fileBase64List syncFile.getFileBase64List(); if (CollectionUtils.is…...
leetcode283-移动零
leetcode 283 思路 本题是通过把数组中所有不为0的数字前置,实现把所有的0后置的效果 双指针法 slow 充当指针,记录当前零应该被移到的位置。而 i 用来遍历整个数组,检查每个元素。如果当前元素不为零,就将其与 slow 位置上的…...
【dify+docker安装教程】
目录 一、dify安装包下载 二、运行环境配置 1、下载docker 2、安装 2.1 新建文件夹 2.2 安装 2.3 命令安装 3.下载完成后需要重启电脑,注意保存文档!!注意保存!!注意!!(血的教…...
GPU虚拟化实现(五)
GPU虚拟化实现(五) 章节回顾初步介绍详细介绍核心数据结构核心功能和运作机制初始化显存分配显存释放显存溢出检查显存类型检查查看分配信息代码执行流程假设例子总结章节回顾 在上一章,简单介绍了项目拦截cuda函数的流程,其本质上与拦截nvml函数的流程是一致的,都是首先…...
C++——入门基础
文章目录 一、前言二、C的发展历史2.1 C的诞生2.2 C的重要性 三、C的应用3.1第一个C程序3.2 C版3.2 C版3.3 C版与C版的区分 3.2 namespace关键字3.2.1 namespace的意义3.2.2C中域的分类3.2.3 namespace的定义3.2.4 namespace的实质3.2.5 namespace的嵌套 3.3 作用域运算符 &…...
AT2401C与RFX2401C问题处理资料
1、AT2401C 可以 PIN 对 PIN 替代 RFX2401C 吗? 答:AT2401C 可以 PIN 对 PIN 替换 RFX2401C;同时 CB2401 也可以 PIN 对 PIN 替换 RFX2401C;我们主要推 AT2401C 这款芯片,如果客户产 品需要过认证或者应用于音频产品建…...
微信小程序连续多个特殊字符自动换行解决方法
效果图 .wxml <view class"container"><text>没转换{{text}}</text><view style"height: 60rpx;" /><text>转换后{{convert}}</text> </view>.js Page({data: {text:!!!&am…...
【Linux实践系列】:进程间通信:万字详解命名管道实现通信
🔥 本文专栏:Linux Linux实践项目 🌸作者主页:努力努力再努力wz 💪 今日博客励志语录: 与其等待完美的风,不如学会在逆风中调整帆的角度——所有伟大航程都始于此刻出发的勇气 ★★★ 本文前置知…...
【TS入门笔记4---装饰器】
TS入门笔记4 TypeScript---装饰器一、装饰器基础1. 定义与作用:装饰器是一种特殊类型的声明,它可以被附加到类声明、方法、访问符、属性或参数上,用来修改类的行为。在 TypeScript 里,装饰器本质上是一个函数,它接收不…...
大学之大:韩国科学技术研究院2025.4.28
韩国科学技术研究院(KAIST)作为韩国理工科教育与科研的旗舰机构,其发展历程深刻反映了韩国从工业化到科技强国的转型轨迹。以下从历史沿革、学科优势、教学特色、科研创新、教育规模、资源投入及未来战略等维度展开全面分析: 一、…...
【QT】QT控制硬件
QT控制硬件 1.上位机程序开发2.具体例子控制led灯3. linux中的函数跟QT类里面的函数同名,发生冲突4.示例代码 1.上位机程序开发 QT做一个上位机程序,控制底层的硬件设备(下位机) 总结: 在构造函数里面去初始化,打开硬件驱动在析…...
Spring的BeanFactory和FactoryBean的区别
BeanFactory和FactoryBean在Spring框架中扮演着不同的角色,具有不同的功能和用途。 定义与角色 BeanFactory:BeanFactory是Spring IoC容器的核心接口,用于管理和维护Bean的定义、创建和生命周期。它是Spring IoC容器的基础&…...
【JavaScript】if语句
JS中的程序是从上到下一行一行执行的。 通过流程控制语句可以控制程序执行流程,使程序可以根据一定的条件来选择执行语句。 语句的分类: 1、条件判断语句 2、条件分支语句 3、循环语句 条件判断语句:使用条件判断语句可以在执行某个语句之前进…...
PostgreSQL oracle_fdw 扩展解析
PostgreSQL oracle_fdw 扩展解析 oracle_fdw 是 PostgreSQL 的一个外部数据包装器(Foreign Data Wrapper)扩展,允许 PostgreSQL 直接连接和操作 Oracle 数据库。以下是全面详细的使用指南: 一、安装与配置 1. 前置要求 Oracle 客户端库:必…...
从信息传输到智能互动,融云的全球智能通信云服务进化
4 月 24 日-25 日,GTC2025 全球流量大会在深圳福田会展中心举办,融云携全球智能通信云解决方案亮相。 在大会首日的开幕式峰会上,融云高级研发总监李宏博受邀分享《从信息传输到智能互动,融云的全球智能通信云服务进化》。 作为连…...
关于https请求丢字符串导致收到报文解密失败问题
加密方法:AES两次URLEncoder 问题现象:服务端收到的报文中少了类似%25这样的字符,导致解密失败 问题分析:用RequestBody接受 也有可能是springboot自动做了一次解码URLDecoder,自己只需要解码一次就好了...
Rust 学习笔记:修复所有权常见错误
Rust 学习笔记:修复所有权常见错误 Rust 学习笔记:修复所有权常见错误错误一:返回栈上的引用错误二:没有足够的权限错误三:别名和可变性错误四:从集合中拷贝一个元素(转移所有权)错误…...
Unity3D引擎框架及用户接口调用方式相关分析及汇总
分析目的 目前外网3D手游绝大部基于Unity3D引擎进行开发,Unity3D引擎属于商业引擎,引擎整理框架的运行机制较为神秘,本文介绍Unity引擎框架、对象组织方式、用户接口与引擎交互方式等原理,通过本文的分析和介绍可了解Unity3D框架中大致执行原理。 实现原理 Unity引擎作为…...
喷泉码在物联网场景下的案例分析
在物联网复杂场景下,无线传感器网络作为信息感知前端,面临能量受限、信道不稳定、多跳传输可靠性差等难题,严重制约物联网系统运行效能。传统基于反馈重传的通信机制在无线传感器网络中难以为继。其 ACK 确认操作频繁,大幅增加能耗,且在动态网络拓扑中,反馈易丢失,致使数…...
OpenCV 图形API(69)图像与通道拼接函数------将一个 GMat 类型的对象转换为另一个具有不同深度GMat对象函数convertTo()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 将一个矩阵转换为另一种数据深度,并可选择进行缩放。 该方法将源像素值转换为目标数据深度。最终应用 saturate_cast<> 以避免…...
考研系列-计算机组成原理第七章、输入/输出系统
一、I/O接口 1.I/O接口概念 现在的I/O接口有些集成在南桥芯片上...
使用vue3 脚手架创建项目
1.创建项目 并 运行 1.1 创建项目 vue create abcd 1.2 运行 创建好项目后,命令行会提示你运行项目 npm run serve 2.介绍各个目录 node_modules : 项目依赖包,其中包括很多基础依赖,自己也可以根据需要安装其他依赖 assets文件夹&a…...
云服务器被黑客攻击应急响应与加固指南(上)
一、入侵检测与应急处理 1. 异常行为检测 # 查看异常登录记录 sudo lastb | awk {print $3} | sort | uniq -c | sort -nr sudo grep "Failed password" /var/log/auth.log | awk {print $11} | sort | uniq -c# 检查可疑进程 ps auxf | grep -E (curl|wget|bash|s…...
联合体union的特殊之处
一个联合体union的长度等于其内部长度最大的成员的长度。 union的所有成员共享同一块内存空间,可以利用这个特性读取数据的字节存储方式。 #include <stdio.h>int check_endian() {union {short s; // 2 字节(short)char c[2]…...
Spring系列五:手动实现Spring底层机制 第三部分
💗实现任务阶段5 🍚bean后置处理器实现 bean后置处理器实现 思路:先完成原生Spring 使用Bean后置处理器的案例, 然后实现自己的bean后置处理器 bean的生命周期~传送门 在idea中 shortcuts: shiftshift , 输入 InitializingBean, 搜索. 在zzw-spring…...
AGV、AMR机器人控制器x86/RK3588/NV各有什么优劣势?
以下是关于AGV/AMR机器人控制器解决方案中x86、RK(瑞芯微)、NV(英伟达)平台优劣势的综合分析: 一、核心性能对比 平台优势局限性适用场景x861. 多核高频CPU支持复杂算法运算,适合大规模路径规划及多机…...