linux、windows 动态库与静态库的实现

news2025/6/11 7:59:34

动态库与静态库的实现

在使用keil的时候遇到这样一个事情,我调用了一个函数,只有函数声明,但是我想查看函数的实现却不行,为什么会这样,这不来了嘛,

我们在使用printf函数等,都是加上头文件直接调用,学校里并没有详细说这个函数的底层实现,以及动态库和静态库的概念

可以理解为我写了一个通用的函数,我只希望别人使用我的函数接口,并不知道我的底层实现,那么我们可以将写的函数放在文件内编译成一个共享库

在C语言开发中,静态库和动态库是两种常见的代码库(Library)类型,它们提供了一种方式来复用代码,允许开发者将常用的函数和资源集中管理。这两种库的主要区别在于它们被链接和加载到程序中的方式。

静态库(Static Libraries)

  • 定义:静态库是一种在程序编译链接阶段被整合到最终可执行文件中的库。它通常包含一组预编译的函数、变量和数据结构,这些可以在多个程序中重复使用。
  • 文件扩展名:在Unix-like系统中,静态库文件通常有.a扩展名(例如,libexample.a);在Windows系统中,扩展名通常是.lib
  • 使用方式:当程序被编译时,静态库中相关的代码会被完整地复制到最终的可执行文件中。这意味着,一旦程序被编译,它就不再依赖于原始的库文件。
  • 优点
    • 可执行文件是自包含的,不需要额外的库文件就可以运行,便于分发。
    • 避免了运行时的库版本冲突问题。
  • 缺点
    • 可能会导致最终的可执行文件体积较大,因为每个程序都包含了一份库的副本。
    • 更新库需要重新编译链接所有使用该库的程序。

动态库(Dynamic Libraries)

  • 定义:动态库是在程序运行时被加载的库。与静态库不同,动态库不会被复制到可执行文件中,而是在程序执行时从外部文件动态加载。
  • 文件扩展名:在Unix-like系统中,动态库文件有.so扩展名(例如,libexample.so);在Windows系统中,扩展名是.dll
  • 使用方式:程序在运行时由动态链接器(runtime linker/loader)加载动态库。这意味着,多个程序可以共享同一份物理库文件,节省资源。
  • 优点
    • 节省磁盘空间和内存,因为库的代码在内存中可以被多个程序共享。
    • 更新库文件时,不需要重新编译链接使用该库的程序。
  • 缺点
    • 程序运行时依赖于外部的库文件,如果库文件丢失或版本不兼容,可能导致程序无法运行。
    • 可能会遇到“地狱依赖”(Dependency Hell)问题,即管理和解决程序依赖的复杂性。

总的来说,静态库和动态库各有优缺点,选择哪一种类型主要取决于项目的具体需求、分发方式和运行环境。

C语言程序的编译过程可以分为四个主要阶段:预处理(Preprocessing)、编译(Compilation)、汇编(Assembly)和链接(Linking)。在这个过程中,静态库和动态库的引入发生在链接阶段。下面是各个阶段的详细介绍:

1. 预处理(Preprocessing)

  • 操作:预处理器处理源代码文件中的预处理指令,如#include#define#ifdef等。这包括展开宏定义,处理条件编译指令,以及包含头文件的内容。
  • 结果:预处理后的源代码,此时所有的宏都已展开,所有的头文件内容都已插入到源代码中。

2. 编译(Compilation)

  • 操作:编译器将预处理后的源代码转换成汇编语言。在这一阶段,编译器会进行语法分析、语义分析、优化等操作。
  • 结果:汇编语言代码,这是一种低级语言,更接近于机器代码但仍然为人类可读。

3. 汇编(Assembly)

  • 操作:汇编器将汇编语言代码转换为机器代码,生成目标文件。目标文件包含了程序的机器语言版本,但还没有解决外部引用。
  • 结果:目标文件(在Unix-like系统中通常是.o.obj文件),包含了编译后的代码和数据,但外部符号引用(如函数调用)尚未解析。

4. 链接(Linking)

  • 操作

    :链接器将一个或多个目标文件与所需的库一起链接,生成最终的可执行文件。在这个阶段,静态库和动态库的引入发生:

    • 静态库:链接器会将程序中实际使用到的静态库中的函数和数据复制到最终的可执行文件中。
    • 动态库:链接器不会将动态库的代码包含到可执行文件中,而是记录动态库的引用。程序运行时,操作系统负责加载这些动态库。
  • 结果:最终的可执行文件。对于静态链接,可执行文件包含了所有必需的库代码;对于动态链接,可执行文件依赖于外部的动态库。

静态库和动态库的引入

  • 静态库:在链接阶段,静态库的相关代码被整合进最终的可执行文件中,使得可执行文件在没有静态库的情况下也能独立运行。
  • 动态库:在链接阶段,只记录对动态库的引用。程序运行时,动态库被操作系统加载,程序中的调用通过动态链接器重定向到这些库中的实现。

所以在使用动态库时我们会将动态库放入运行的环境中,这是有门槛的

放在哪里?

动态库和操作系统

  • 动态链接器:操作系统的一部分,负责运行时解析程序对动态库函数的引用,加载库到内存,以及管理库之间的依赖关系。在Linux和Unix-like系统中,动态链接器通常是ld-linux.so,在Windows中是Windows Loader
  • 环境依赖:因为动态库的这些特性,它们主要用于有完整操作系统支持的环境中,如桌面操作系统、服务器操作系统或者嵌入式操作系统等。

嵌入式系统和动态库

在嵌入式系统中,是否使用动态库取决于嵌入式操作系统的功能和资源限制:

  • 有操作系统的嵌入式环境:对于运行Linux、RTOS(实时操作系统)或其他具有动态链接能力的嵌入式操作系统的设备,可以使用动态库。例如,基于Linux的嵌入式系统可以利用动态库来节省内存和存储空间,同时提高代码重用。
  • 无操作系统或裸机(Bare-metal)环境:在没有操作系统的嵌入式环境中,通常不使用动态库。这些环境下的程序直接在硬件上运行,没有动态链接器来管理运行时的库加载。在这种情况下,通常会使用静态库或直接将代码编译到可执行文件中。

所以在使用嵌入式设备时候,只有在使用操作系统时,并且含有动态链接器时,才可以使用动态库

下面分别在linux环境与windows环境下制作一个动态库与静态库

linux与windows下 动态库与静态库的后缀

Linux

  • 动态库:

    .so
    

    (Shared Object)

    • 例如,libexample.so
  • 静态库:

    .a
    

    (Archive)

    • 例如,libexample.a

在Linux中,动态库通常以.so为后缀,表示这是一个共享对象文件,可以在运行时被多个程序共享。静态库以.a为后缀,表示这是一个归档文件,包含了一组被编译过的对象文件,链接器在构建可执行文件时会从中提取必要的对象。

Windows

  • 动态库:

    .dll
    

    (Dynamic-Link Library)

    • 例如,example.dll
  • 静态库:

    .lib
    
    • 例如,example.lib

在Windows中,动态库以.dll为后缀,表示这是一个动态链接库文件,它包含了可以被多个程序共享的函数和资源。静态库使用.lib后缀,虽然在某些情况下.lib文件也可以用于动态链接(作为导入库),但通常.lib用于静态链接,包含了直接链接到最终可执行文件中的代码和数据。windows下的静态库也可以是.a后缀

下面使用一个简单的示例程序来制作一个静态库与动态库, 写四个文件,函数分别为加减乘除,并在一个共有的头文件中进行声明

linux下静态库的制作

为了创建一个包含加、减、乘、除四个基本数学运算的静态库(我们将其命名为libmathops),需要编写四个源文件和一个头文件。下面是这些文件的内容和制作静态库的步骤:

步骤 1: 编写源文件和头文件

touch add.c subtract.c multiply.c divide.c mathops.h

image-20240309141916975

add.c

#include "mathops.h"

int add(int a, int b) {
    return a + b;
}

subtract.c

#include "mathops.h"

int subtract(int a, int b) {
    return a - b;
}

multiply.c

#include "mathops.h"

int multiply(int a, int b) {
    return a * b;
}

divide.c

#include "mathops.h"

float divide(int a, int b) {
    if (b != 0) return (float)a / b;
    return 0.0; // Error case
}

mathops.h

#ifndef MATHOPS_H
#define MATHOPS_H

int add(int a, int b);
int subtract(int a, int b);
int multiply(int a, int b);
float divide(int a, int b);

#endif

以上一共是五个文件,四个函数文件 一个函数声明

步骤 2: 编译源文件

使用GCC编译器编译每个源文件,生成目标文件(.o 文件):

gcc -c add.c
gcc -c subtract.c
gcc -c multiply.c
gcc -c divide.c

这些命令会生成add.osubtract.omultiply.odivide.o目标文件。

image-20240309142336903

文件过多自然而然就引入makefile了

步骤 3: 创建静态库

使用ar工具将所有目标文件打包成一个静态库文件:

ar rcs libmathops.a add.o subtract.o multiply.o divide.o

这个命令创建了一个名为libmathops.a的静态库文件,包含了之前编译的所有目标文件。

image-20240309142404314

步骤 4: 使用静态库

现在可以在其他程序中使用这个静态库了。假设有一个main.c文件,使用了这个库:

#include <stdio.h>
#include "mathops.h"

int main() {
    int sum = add(1, 2);
    int difference = subtract(10, 5);
    int product = multiply(4, 5);
    float quotient = divide(20, 4);

    printf("Sum: %d\n", sum);
    printf("Difference: %d\n", difference);
    printf("Product: %d\n", product);
    printf("Quotient: %f\n", quotient);

    return 0;
}

编译这个程序并链接静态库:

gcc -o main main.c -L. -lmathops

这里,-L.指定了库文件搜索路径(当前目录),-lmathops指定了要链接的库(去掉前缀lib和后缀.a)。

完成以上步骤后,就成功创建了一个静态库,并在一个程序中使用了它。

image-20240309142851006

linux下动态库的制作

还是以上的文件

步骤 1: 编译源文件为共享对象

使用GCC编译器编译每个源文件,不过这次我们需要添加-fPIC选项来生成位置无关代码(Position Independent Code),这是创建动态库所必需的。然后,使用-shared选项将这些目标文件链接为一个动态库文件。

gcc -fPIC -c add.c
gcc -fPIC -c subtract.c
gcc -fPIC -c multiply.c
gcc -fPIC -c divide.c
gcc -shared -o libmathops.so add.o subtract.o multiply.o divide.o

这些命令会生成libmathops.so动态库文件。-fPIC选项是为了确保正确生成动态库所需的可重定位代码。-shared选项告诉编译器生成动态链接库而不是可执行文件。

image-20240309143228599

步骤 2: 使用动态库

为了使用这个动态库,需要确保编译器在编译时能找到库的头文件,链接器在链接时能找到库文件,运行时动态链接器(如ld-linux.so)也能找到这个库文件。

还是原来的main.c文件,内容如下:

#include <stdio.h>
#include "mathops.h"

int main() {
    int sum = add(1, 2);
    int difference = subtract(10, 5);
    int product = multiply(4, 5);
    float quotient = divide(20, 4);

    printf("Sum: %d\n", sum);
    printf("Difference: %d\n", difference);
    printf("Product: %d\n", product);
    printf("Quotient: %f\n", quotient);

    return 0;
}

编译并链接这个程序,同时指定动态库的位置:

gcc -o main main.c -L. -lmathops

如果现在运行会提示找不到动态库

image-20240309143359213

步骤 3: 确保运行时能找到动态库

在运行程序之前,你需要确保动态链接器能找到libmathops.so。在Linux中,你可以通过设置LD_LIBRARY_PATH环境变量来实现:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.

这会临时添加当前目录到动态链接器的搜索路径中。然后,就可以运行你的程序了:

./main

如果一切正常,你的程序会使用动态库中的函数,并输出正确的结果。

image-20240309143516877

注意

  • 将动态库放在标准库路径(如/usr/lib/lib)或使用ldconfig命令更新动态链接器的缓存,可以避免设置LD_LIBRARY_PATH
  • 分发包含动态库的程序时,确保接收方也有途径获取并正确安装这个库。

使用export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.命令临时添加当前目录到动态链接器的搜索路径中,这个设置的有效期限是当前终端会话的生命周期。换句话说,这个设置只在你当前打开的这个终端窗口(或会话)中有效。一旦你关闭这个终端窗口或开启一个新的终端会话,这个设置就会失效,LD_LIBRARY_PATH环境变量会恢复到其默认值或是在其他地方(如你的shell配置文件中)设定的值。

我们现在重新打开命令窗口,试着运行一下main 提示找不到

image-20240309143804211

试着将动态库拷贝到/usr/lib或/lib 目录下 (现在是拷贝到根文件的lib目录下)

image-20240309144149200

运行成功

image-20240309144325399

windows下静态库的制作

安装windows版gcc

在Windows下制作静态库通常涉及到使用Microsoft Visual Studio的编译器(MSVC)或MinGW(一个适用于Windows的GCC版本)。这里使用MinGW GCC

首先需要安装MinGW,并下载安装gcc,其次配置环境变量

https://sourceforge.net/projects/mingw-w64/files/

安装参考链接:https://blog.csdn.net/jjxcsdn/article/details/123058745?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170995448716800185835800%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=170995448716800185835800&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-1-123058745-null-null.142v99pc_search_result_base7&utm_term=MinGW&spm=1018.2226.3001.4187

有的是下载MinGW选择安装,这个添加环境变量直接使用

image-20240309150839373

image-20240309150810947

在Windows平台上,静态库文件通常有两种后缀:.lib.a。这两种后缀的主要区别在于它们通常与不同的开发工具链相关联,尽管它们的功能和目的非常相似。

.lib 文件

  • 开发工具链.lib 文件通常与Microsoft Visual Studio和其他基于Windows的开发环境相关联。
  • 用途:在这些环境中,.lib 文件用作静态库,包含了可直接链接到最终可执行文件的编译代码。此外,.lib 文件也可以作为动态链接库(DLL)的导入库,其中包含了必要的信息以便在编译时解析对DLL中函数的引用,但实际的函数实现在相应的.dll文件中。

.a 文件

  • 开发工具链.a 文件通常与GCC(GNU Compiler Collection)相关联,包括在Windows上使用的MinGW(Minimalist GNU for Windows)或Cygwin这样的工具。
  • 用途:在这些环境中,.a 文件用作静态库,包含了可以被链接器整合到最终可执行文件中的编译代码。

区别和兼容性

  • 主要区别:这两种文件格式的主要区别在于它们各自支持的工具链。.lib 文件格式紧密与Microsoft的工具链集成,而.a 文件格式则与GCC和类Unix环境的工具链集成。
  • 兼容性:尽管这两种文件在格式上可能有所不同,但它们的基本目的和功能是相同的——都是为了提供一种方式,将预编译的代码库整合到最终的应用程序中。在某些情况下,特定的工具可能能够读取或转换这两种格式之间的文件,但这通常不是默认行为,可能需要额外的步骤或工具。

选择哪一个

  • 选择.lib还是.a主要取决于你使用的开发环境和工具链。如果你主要在Visual Studio或其他基于Windows的环境中开发,.lib可能是更自然的选择。如果你使用GCC、MinGW或Cygwin等工具,.a文件可能更合适。
  • 在跨平台开发中,如果可能,提供两种格式的静态库可以增加库的可用性,让不同环境下的开发者都能方便地使用你的库。

使用gcc工具链命令与linux下的一样,这里不做阐述,演示lib的静态库如何创建(不使用gcc工具链) 使用keil软件生成静态链接库

新建工程(ARM架构随便选)–》加入四个文件

image-20240309155939374

输出勾选lib文件,在输出的文件中找到lib

image-20240309160023998

将lib文件添加到其他工程中包含头文件即可调用

https://txbook.readthedocs.io/zh-cn/latest/keil_output_lib.html

windows下动态库的制作

还是刚才的文件

gcc -shared -o mathops.dll add.c subtract.c multiply.c divide.c -Wl,--out-implib,libmathops.a
gcc -o main.exe main.c -L. -lmathops
./main

其中

gcc -shared -o mathops.dll add.c subtract.c multiply.c divide.c -Wl,--out-implib,libmathops.a 解释

这条命令使用GCC编译器在Windows平台上创建一个动态链接库(DLL)文件mathops.dll,并且同时生成一个导入库libmathops.a。这个命令涵盖了编译和链接两个阶段,具体解释如下:

  • gcc:调用GNU编译器集合(GCC),这是一个支持多种编程语言的编译器,常用于编译C和C++程序。
  • -shared:这个选项告诉GCC生成一个共享库(在Windows上是DLL)。共享库可以被多个程序在运行时共享,这与静态库(在程序编译时整合进可执行文件)相对。
  • -o mathops.dll:指定输出文件的名称和类型。这里,输出文件被命名为mathops.dll.dll扩展名表示这是一个Windows动态链接库文件。
  • add.c subtract.c multiply.c divide.c:这些是源代码文件,包含了你想要编译进动态库的函数定义。在这个例子中,假设这些文件分别定义了加法、减法、乘法和除法操作。
  • -Wl,--out-implib,libmathops.a:这个选项用于向链接器(ld)传递参数:
    • -Wl,:告诉GCC将后面的选项传递给链接器。
    • --out-implib,libmathops.a:指示链接器生成一个导入库(libmathops.a),这个库在将来链接到这个DLL的时候会用到。导入库包含了动态库中公开函数的符号引用,使得其他使用这个DLL的程序可以在编译时解析这些符号。

文件下载

https://newbie-typora.oss-cn-shenzhen.aliyuncs.com/zhongke/language_c.zip

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1504226.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HarmonyOS NEXT应用开发案例——列表编辑实现

介绍 本示例介绍用过使用ListItem组件属性swipeAction实现列表左滑编辑效果的功能。 该场景多用于待办事项管理、文件管理、备忘录的记录管理等。 效果图预览 使用说明&#xff1a; 点击添加按钮&#xff0c;选择需要添加的待办事项。长按待办事项&#xff0c;点击删除后&am…

考研408 2014年第41题(二叉树带权路径长度【WPL】)

function.h(结构体)&#xff1a; // // Created by legion on 2024/3/5. //#ifndef INC_14_4_TREE_FUNCTION_H #define INC_14_4_TREE_FUNCTION_H #include <stdio.h> #include <stdlib.h>typedef int BiElemType; typedef struct BiTNode{BiElemType weight;//直…

【Python】Python Astar算法生成最短路径GPS轨迹

简介 最短路径问题是计算机科学中一个经典问题&#xff0c;它涉及找到图中两点之间距离最短的路徑。在实际应用中&#xff0c;最短路径算法用于解决广泛的问题&#xff0c;例如导航、物流和网络优化。 步骤 1&#xff1a;加载道路网络数据 要计算最短路径&#xff0c;我们需…

【Python】装饰器函数

专栏文章索引&#xff1a;Python 原文章&#xff1a;装饰器函数基础_装饰函数-CSDN博客 目录 1. 学习装饰器的基础 2.最简单的装饰器 3.闭包函数装饰器 4.装饰器将传入的函数中的值大写 5. 装饰器的好处 6. 多个装饰器的执行顺序 7. 装饰器传递参数 8. 结语 1. 学习装饰…

【UE5】创建蓝图

创建GamePlay需要的相关蓝图 项目资源文末百度网盘自取 在 内容游览器 文件夹中创建文件夹&#xff0c;命名为 Blueprints &#xff0c;用来放这个项目的所有蓝图(Blueprint) 在 Blueprints 文件夹下新建文件夹 GamePlay ,用存放GamePlay相关蓝图 在 Blueprints 文件夹下创建文…

Java17 --- SpringCloud初始项目创建

目录 一、cloud项目创建 1.1、项目编码规范 1.2、注解生效激活 1.3、导入父工程maven的pom依赖 二、创建子工程并导入相关pom依赖 2.1、相关配置文件 2.1.1、数据库配置文件内容 2.1.2、自动生成文件配置内容 三、创建微服务8001子工程 3.1、导入相关pom依赖 3.…

利用IDEA创建Java项目使用Servlet工具

【文件】-【项目结构】 【模块】-【依赖】-【】-【JAR】 找到Tomcat的安装路径打开【lib】找到【servlet.jar】点击【确定】 勾选上jar,然后【应用】-【确定】 此时新建文件可以发现多了一个Servlet&#xff0c;我们点击会自动创建一个继承好的Servlet类

对比学习概念与如何标注标签

对比学习公式讲述 对比学习倾向于将同一图像的转换视图之间的一致性最大化&#xff0c;而将不同图像的转换视图之间的一致性最小化。令是一个输出特征空间的卷积神经网络。一个图像x的两个增广图像补丁通过进行映射&#xff0c;生成一个查询特征q和一个关键特征k。此外&#x…

ospf静态路由实验简述

1、ospf静态路由实验简述 实验拓扑图 实验命令 r2: sys sysname r2 undo info enable int loopb 0 ip add 2.2.2.2 32 quit int e0/0/0 ip add 23.1.1.2 24 quit ospf 1 area 0 network 23.1.1.0 0.0.0.255 network 2.2.2.2 0.0.0.0 ret r3: sys sysname r3 undo info enable …

2024pytest自动化测试框架学习(二)

在自动化测试中&#xff0c;参数化非常常见。当你在测试某一个接口时&#xff0c;通常会给测试函数传递很多参数&#xff0c;达到遍历的目的。比如测试登录接口&#xff0c;我们需要模拟各种场景的账号密码。又如我们上一篇文章中介绍的获取天气接口&#xff0c;你需要验证很多…

面向切面编程(AOP)介绍(横切关注点、通知(增强)、连接切入点、切面)

1. 面向切面编程思想AOP AOP&#xff1a;Aspect Oriented Programming面向切面编程 AOP可以说是OOP&#xff08;Object Oriented Programming&#xff0c;面向对象编程&#xff09;的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构&#xff0c;用于模拟公…

docker-swarm集群搭建

目录 一、docker swarm介绍 二、部署docker 三、搭建集群 3.1 工作模式 3.2 将当前主机作为leader 3.3 将第二个节点slave1加入到worker 3.4 将第三个节点slave2也加入到worker 3.5 将第四个节点(slave3)加入到manager 四、总结 一、docker swarm介绍 Docker Swarm…

解锁安卓开发利器:深度探析ADB【安卓开发】

引言 在安卓开发与维护过程中&#xff0c;我们经常会遇到一些限制&#xff0c;比如无法直接访问某些系统功能&#xff0c;或者在某些定制系统中 受到限制 。为了解决这些问题&#xff0c;我们需要一种有效的工具来管理和调试安卓设备&#xff0c;而这时候ADB&#xff08;Andro…

如何变得心智成熟?我推荐你读这5本书

一个人若总是在底层混&#xff0c;说明他的脑子确实不怎么样&#xff0c;一群底层的人聚在一起就更完蛋。 变化是常态&#xff0c;成长是选择。无法否定过去相信的东西&#xff0c;是你最大的障碍。 今天&#xff0c;为大家推荐一份“心智书单”。 01 《打开心智》 李睿秋提…

《汇编语言》- 读书笔记 - 第16章-直接定址表

《汇编语言》- 读书笔记 - 第16章-直接定址表 16.1 描述了单元长度的标号&#xff08;数据标号&#xff09;检测点 16.1 16.2 在其他段中使用数据标号assume通过标号取地址检测点 16.2 16.3 直接定址表&#xff08;Direct Addressing Table&#xff09;例1分析代码效果 例2分析…

HPE ProLiant MicroServer Gen8驱动程序下载(windows)

记录下&#xff0c;以方便需要重装系统时将驱动更新到最后版本。 共有下面设备有适用的驱动可用&#xff1a; 1、系统管理&#xff1a; iLO 4 Channel Interface Driver for Windows Server 2016 下面这个驱动&#xff0c;安装后不知道有什么用 iLO 3/4 Management Control…

人力资源社会保障部教育部关于印发《关于深化中小学教师职称制度改革的指导意见》的通知

人力资源社会保障部、教育部印发 关于《深化中小学教师职称制度改革的指导意见》的通知 人社部发[2015]79号 各省、自治区、直辖市及新疆生产建设兵团人力资源社会保障厅&#xff08;局&#xff09;、教育部门&#xff08;教委、教育局&#xff09;&#xff1a; 为深化教育…

java——枚举,lambda

文章目录 枚举的使用使用场景switch语句常用方法 lambdalambda的前置知识什么是函数式接口 lambda的基本语法lambda注意事项 枚举的使用 枚举是在JDK1.5以后引入的。主要用途是&#xff1a;将一组常量组织起来&#xff0c;在这之前表示一组常量通常使用定义常量的方 式 publi…

OpenCV学习笔记(四)——对视频的读取操作

目录 读取视频内容 将彩色视频转换为灰色视频 读取视频内容 读取视频文件通常分为读取文件、验证是否打开成功打开文件、逐帧读取视频文件、释放资源和关闭窗口 &#xff08;1&#xff09;读取文件 在OpenCV中&#xff0c;通常使用VedioCapture来读取视频流&#xff0c;Vedi…

Vue.js数据绑定解密:深入探究v-model和v-bind的原理与应用

hello宝子们...我们是艾斯视觉擅长ui设计和前端开发10年经验&#xff01;希望我的分享能帮助到您&#xff01;如需帮助可以评论关注私信我们一起探讨&#xff01;致敬感谢感恩&#xff01; Vue.js数据绑定解密&#xff1a;深入探究v-model和v-bind的原理与应用 一、引言 Vue.…