当前位置: 首页 > news >正文

OpenHarmony napi 编译 .so 并打包成 .har

一、前言

最近在搞公司标准产品适配OpenHarmony 平台, 按照行业上的常用方法,在Android 是将底层代码用c++ 封装成 xxx.so  ,然后将其他一部分打包成 xxx.jar。 因此,在OpenHarmony 平台也是打算按照这个模式。正所谓,好记忆,不如烂笔头,写下这篇文章,以后也可以翻阅查看。

二、相关概念

1. Android 平台

1.1 xxxx.so

静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。编译之后程序文件大,但加载快,隔离性也好。 动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。多个应用程序可以使用同一个动态库,启动多个应用程序的时候,只需要将动态库加载到内存一次即可。一般Linux 编译为xx.so   Windows 编译为  xxx.dll.

编译动态库:

在Linux Android  

-shared 该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件 -fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。 -L.:表示要连接的库在当前目录中 -ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称。

1.2 xxx.jar  

在Java开发中,JAR(Java Archive)是一种常见的文件格式,用于不同的场景。
JAR包是Java的类进行编译生成的class文件打包的压缩包,通常用于存放类库和依赖。在开发过程中,我们经常需要引用一些通用的类,将这些类打包成JAR包便于管理和使用。例如,当我们使用某些功能时,就需要导入支持这些功能的JAR包。

2. OpenHarmony 平台

2.1 xxx.so

静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。编译之后程序文件大,但加载快,隔离性也好。 动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。多个应用程序可以使用同一个动态库,启动多个应用程序的时候,只需要将动态库加载到内存一次即可。

2.2 xxxx.har

在OpenHarmony 中,这个是新平台,因此也有跟Android 相类似的技术。

在 华为开发者文档有提到相关概念

应用程序包概述-应用程序包基础知识-开发基础知识-入门 | 华为开发者联盟 (huawei.com)

2.2.1 应用程序包概述

用户应用程序泛指运行在设备的操作系统之上,为用户提供特定服务的程序,简称“应用”。一个应用所对应的软件包文件,称为“应用程序包”。

HarmonyOS提供了应用程序包开发、安装、查询、更新、卸载的管理机制,方便开发者开发和管理HarmonyOS应用,具体如下:

  • 应用软件所涉及的文件多种多样,开发者可通过HarmonyOS提供的集成开发工具将其开发的可执行代码、资源、三方库等文件整合到一起制作成HarmonyOS应用程序包,便于开发者对应用程序的部署。

  • 应用软件所涉及的设备类型多种多样,开发者可通过HarmonyOS提供的应用程序包配置文件指定其应用程序包的分发设备类型,便于应用市场对应用程序包的分发管理。

  • 应用软件所包含的功能多种多样,将不同的功能特性按模块来划分和管理是一种良好的设计方式。HarmonyOS提供了同一应用程序的多包管理的机制,开发者可以将不同的功能特性聚合到不同的包中,方便后续的维护与扩展。

  • 应用软件涉及的芯片平台多种多样,有x86、ARM等,还有32位、64位之分,HarmonyOS为应用程序包屏蔽了芯片平台的差异,使应用程序包在不同的芯片平台都能够安装运行。

  • 应用软件涉及的软件信息多种多样,有应用版本、应用名称、组件、申请权限等的信息,HarmonyOS包管理为开发者提供了这些信息的查询接口,方便开发者在程序中查询所需要的包信息。

  • 应用软件涉及的资源多种多样,有媒体资源、原生资源、字符资源以及国际化的资源等,HarmonyOS包管理将不同的资源归档到不同的目录中,并集成资源索引文件,方便应用对资源的查找和使用。

2.2.2 应用程序包结构

在OpenHarmony 中应用程序包分为两种结构:

  • Stage模型应用程序包结构
  • FA模型应用程序包结构

2.3.1 基于Stage模型的应用结构

基于Stage模型开发的应用,经编译打包后,其应用程序包结构如下图应用程序包结构(Stage模型)所示:

在开发态,一个应用包含一个或者多个Module,可以在DevEco Studio工程中创建一个或者多个Module。Module是HarmonyOS应用/服务的基本功能单元,包含了源代码、资源文件、第三方库及应用/服务配置文件,每一个Module都可以独立进行编译和运行。

Module分为“Ability”和“Library”两种类型,“Ability”类型的Module对应于编译后的HAP(Harmony Ability Package)

“Library”类型的Module对应于HAR(Harmony Archive),或者HSP(Harmony Shared Package)。

其中,

开发者通过DevEco Studio把应用程序编译为一个或者多个.hap后缀的文件,即HAPHAP是HarmonyOS应用安装的基本单位,包含了编译后的代码、资源、三方库及配置文件。

打包后的HAP包结构包括ets、libs、resources等文件夹和resources.index、module.json、pack.info等文件。

  • ets目录用于存放应用代码编译后的字节码文件。
  • libs目录用于存放库文件。库文件是HarmonyOS应用依赖的第三方代码(.so二进制文件)
  • resources目录用于存放应用的资源文件(字符串、图片等),便于开发者使用和维护,详见资源分类与访问。
  • resources.index是资源索引表,由IDE编译工程时生成。
  • module.json是HAP的配置文件,内容由工程配置中的module.json5和app.json5组成,该文件是HAP中必不可少的文件。IDE会自动生成一部分默认配置,开发者按需修改其中的配置。详细字段请参见应用配置文件。
  • pack.info是Bundle中用于描述每个HAP属性的文件,例如app中的bundleName和versionCode信息、module中的name、type和abilities等信息,由IDE工具生成Bundle包时自动生成。

 应用程序包结构(Stage模型)

2.2.3 共享包概述

HarmonyOS提供了两种共享包,HAR(Harmony Archive)静态共享包,和HSP(Harmony Shared Package)动态共享包。

HAR与HSP都是为了实现代码和资源的共享,都可以包含代码、C++库、资源和配置文件.

 HAR和HSP在APP包中的形态示意图

2.2.3.1 HAR

HAR中的代码和资源跟随使用方编译,如果有多个使用方,它们的编译产物中会存在多份相同拷贝.

2.2.3.2 HSP

HSP中的代码和资源可以独立编译,运行时在一个进程中代码也只会存在一份。

HAR不同于HAP,不能独立安装运行在设备上,只能作为应用模块的依赖项被引用。

三、HAR模式创建工程

HAR-共享包-应用程序包基础知识-开发基础知识-入门 | 华为开发者联盟 (huawei.com)

2.1 创建HAR工程

通过DevEco Studio创建一个HAR模块,详见创建库模块。HAR模块默认不开启混淆能力,开启混淆能力,需要把HAR模块的build-profile.json5文件中的artifactType字段设置为obfuscation,配置如下所示:

{"apiType": "stageMode","buildOption": {"artifactType": "obfuscation"}
}

artifactType字段有以下两种取值,默认缺省为original。

  • original:不混淆。
  • obfuscation:混淆。

需要对代码资产进行保护时,建议开启混淆能力,混淆能力开启后,DevEco Studio在构建HAR时,会对代码进行编译、混淆及压缩处理,保护代码资产。

注意:artifactType字段设置为obfuscation时,apiType字段必须设置为stageMode,因为Stage模型才支持混淆。

2.2 HAR开发注意事项

  • HAR不支持在配置文件中声明abilities、extensionAbilities组件。
  • HAR不支持在配置文件中声明pages页面。
  • HAR不支持在build-profile.json5文件的buildOption中配置worker。
  • FA模型与Stage模型的HAR不支持相互引用。
  • Stage模型的HAR,不能引用AppScope内的内容。在编译构建时AppScope中的内容不会打包到HAR中,导致HAR资源引用失败。

2.3 导出HAR的ArkUI组件、接口、资源

2.3.1 Index.ets接口文件

Index.ets文件是HAR导出声明文件的入口,HAR需要导出的接口,统一在Index.ets文件中导出。Index.ets文件是DevEco Studio默认自动生成的,用户也可以自定义,在模块的oh-package.json5文件中的main字段配置入口声明文件,配置如下所示:

{"main": "Index.ets"
}

2.3.2 导出ArkUI组件

ArkUI组件的导出方式与ts的导出方式一致,通过export导出ArkUI组件,示例如下:

// library/src/main/ets/components/MainPage/MainPage.ets
@Component
export struct MainPage {@State message: string = 'Hello World'build() {Row() {Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)}.width('100%')}.height('100%')}
}

HAR对外暴露的接口,在Index.ets导出文件中声明如下所示:

// library/Index.ets
export { MainPage } from './src/main/ets/components/MainPage/MainPage'

2.3.3 导出ts类和方法

// library/src/main/ts/test.ets
export class Log {static info(msg: string) {console.info(msg);}
}export function func() {return "har func";
}export function func2() {return "har func2";
}

HAR对外暴露的接口,在Index.ets导出文件中声明如下所示:

// library/Index.ets
export { Log } from './src/main/ts/test'
export { func } from './src/main/ts/test'
export { func2 } from './src/main/ts/test'

2.3.4 导出native方法

在HAR中也可以包含C++编写的so。对于so中的native方法,HAR通过以下方式导出,以导出libnative.so的加法接口add为例:

// library/src/main/ets/utils/nativeTest.ts
import native from "libnative.so"export function nativeAdd(a: number, b: number) {let result: number = native.add(a, b);return result;
}

HAR对外暴露的接口,在Index.ets导出文件中声明如下所示:

// library/Index.ets
export { nativeAdd } from './src/main/ets/utils/nativeTest'

2.3.5 资源

HAR模块编译打包时会把资源打包到HAR中。在编译构建HAP时,DevEco Studio会从HAP模块及依赖的模块中收集资源文件,如果不同模块下的资源文件出现重名冲突时,DevEco Studio会按照以下优先级进行覆盖(优先级由高到低):

  • AppScope(仅API9的Stage模型支持)。
  • HAP包自身模块。
  • 依赖的HAR模块,如果依赖的多个HAR之间有资源冲突,会按照依赖顺序进行覆盖(依赖顺序在前的优先级较高)。

2.3.6 HAR工程编译

开发及引用静态共享包(API 9)-开发及引用共享包-应用/服务开发-DevEco Studio使用指南-工具 | 华为开发者联盟 (huawei.com)

2.3.6.1 创建库模块
  1. 鼠标移到工程目录顶部,单击右键,选择New > Module,在工程中添加模块。
  2. Choose Your Ability Template界面中,选择Static Library,并单击Nex

3. 在Configure New Module界面中,设置新添加的模块信息,设置完成后,单击Finish完成创建。

  • Module name:新增模块的名称。
  • Language:开发语言。
  • Device type:支持的设备类型。
  • Enable native:是否创建一个用于调用C++代码的模块

创建完成后,会在工程目录中生成库模块及相关文件。

库模块的工程结构,如下图所示:

相关字段的描述如下,其余字段与Entry或Feature模块相关字段相同,可参考工程介绍。

  • libs:用于存放.so文件。
  • src > main > cpp > types:用于存放C++ API描述文件,子目录按照so维度进行划分。
  • src > main > cpp > types > liblibrary > index.d.ts:描述C++接口的方法名、入参、返回参数等信息。
  • src > main > cpp > types > liblibrary > oh-package.json5:描述so三方包声明文件入口和so包名信息。
  • src > main > cpp > CMakeLists.txt:CMake配置文件,提供CMake构建脚本。
  • src > main > cpp > hello.cpp:共享包C++代码源文件。
  • index.ets:共享包导出声明的入口。
2.3.6.2 编译库模块

开发完库模块后,选中模块名,然后通过DevEco Studio菜单栏的Build > Make Module ${libraryName}进行编译构建,生成HAR。HAR可用于工程其它模块的引用,或将HAR上传至ohpm仓库,供其他开发者下载使用。若部分源码文件不需要打包至HAR中,可通过创建.ohpmignore文件,配置打包时要忽略的文件/文件夹。

编译构建的HAR可在模块下的build目录下获取,包格式为*.har。

在编译构建HAR时,请注意以下事项:

  • 在编译构建HAR的过程中,不会将模块中的C++代码直接打包进.har文件中,而是将C++代码编译成动态依赖库.so文件放置在.har文件中的libs目录下。
  • 在编译构建HAR的过程中,会生成资源文件ResourceTable.txt,以便编辑器可以对HAR中的资源文件进行联想。因此,如果不使用DevEco Studio对HAR进行构建,则DevEco Studio的编辑器会无法联想HAR中的资源。
2.3.6.3 发布HAR

文档中心

1. 在库模块中(与src文件夹同一级目录下),添加如下文件:

    • 新建README.md文件:在README.md文件中必须包含包的介绍和引用方式,还可以根据包的内容添加更详细介绍。
    • 新建CHANGELOG.md文件:填写HAR的版本更新记录。
    • 添加LICENSE文件:LICENSE许可文件。

  1. 重新编译库模块,生成*.har文件。
  2. 利用工具ssh-keygen生成公、私钥,可执行以下命令.

四、引用HAR的ArkUI组件、接口、资源

文档中心

引用HAR前,需要先配置对HAR的依赖,配置方式可参考引用HAR文件和资源。

4.1 配置app 工程 HAR 依赖

引用三方HAR,包括从仓库进行安装、从本地文件夹和本地压缩包中进行安装三种方式。

4.1.1 引用ohpm仓中的HAR,首先需要设置三方HAR的仓库信息。DevEco Studio默认仓库地址为OpenHarmony三方库中心仓,如果您需要设置自定义仓库,请在DevEco Studio的Terminal窗口执行如下命令(执行命令前,请确保将DevEco Studio中ohpm安装bin目录配置在“环境变量-系统变量-PATH”中,第一次配置环境变量后,需重启DevEco Studio):

ohpm config set registry your_registry1,your_registry2

说明:ohpm支持多个仓库地址,采用英文逗号分隔。

然后通过如下两种方式设置三方包依赖信息:

方式一:在Terminal窗口中,执行如下命令安装三方包,DevEco Studio会自动在工程的oh-package.json5中自动添加三方包依赖。

ohpm install @ohos/lottie

方式二:在工程的oh-package.json5中设置三方包依赖,配置示例如下:

"dependencies": {"@ohos/lottie": "^2.0.0"
}

依赖设置完成后,需要执行ohpm install命令安装依赖包,依赖包会存储在工程的oh_modules目录下。

ohpm install

4.2 引用本地HAR包

引用本地HAR包,有如下两种方式:

方式一:在Terminal窗口中,执行如下命令进行安装,并会在oh-package.json5中自动添加依赖。

ohpm install ./package.har

方式二:在工程的oh-package.json5中设置三方包依赖,配置示例如下:

"dependencies": {"package": "file:./package.har"
}

依赖设置完成后,需要执行ohpm install命令安装依赖包,依赖包会存储在工程的oh_modules目录下。

ohpm install

在引用共享包时,请注意以下事项:

当前只支持在模块和工程下的oh-package.json5文件中声明dependencies依赖,才会被当做依赖使用,并在编译构建过程中进行相应的处理。

4.3 引用HAR的ArkUI组件

HAR的依赖配置成功后,可以引用HAR的ArkUI组件。ArkUI组件的导入方式与ts的导入方式一致,通过import引入HAR导出的ArkUI组件,示例如下所示:

// entry/src/main/ets/pages/Index.ets
import { MainPage } from "library"@Entry
@Component
struct Index {@State message: string = 'Hello World'build() {Row() {// 引用HAR的ArkUI组件MainPage()Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)}.width('100%')}.height('100%')}
}

4.4 引用HAR的ts类和方法

通过import引用HAR导出的ts类和方法,示例如下所示:

// entry/src/main/ets/pages/Index.ets
import { Log } from "library"
import { func } from "library"@Entry
@Component
struct Index {build() {Row() {Column() {Button('Button').onClick(()=>{// 引用HAR的类和方法Log.info("har msg");func();})}.width('100%')}.height('100%')}
}

4.5 引用HAR的native方法

通过import引用HAR导出的native方法,示例如下所示:

// entry/src/main/ets/pages/Index.ets
import { nativeAdd } from "library"@Entry
@Component
struct Index {@State message: string = 'Hello World'build() {Row() {Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)Button('nativeAdd(1, 2)').onClick(()=> {this.message = "result: " + nativeAdd(1, 2);})}.width('100%')}.height('100%')}
}

4.6 引用HAR的资源

通过$r引用HAR中的资源,例如在HAR模块的src/main/resources里添加字符串资源(在string.json中定义,name:hello_har)和图片资源(icon_har.png),然后在Entry模块中引用该字符串和图片资源的示例如下所示:

// entry/src/main/ets/pages/Index.ets
@Entry
@Component
struct Index {build() {Row() {Column() {// 引用HAR的字符串资源Text($r("app.string.hello_har")).fontSize(50).fontWeight(FontWeight.Bold)// 引用HAR的图片资源Image($r("app.media.icon_har"))}.width('100%')}.height('100%')}
}

/**
 *         ┏┓   ┏┓+ +
 *        ┏┛┻━━━┛┻┓ + +
 *        ┃       ┃
 *        ┃   ━   ┃ ++ + + +
 *        ████━████ ┃+
 *        ┃       ┃ +
 *        ┃   ┻   ┃
 *        ┃       ┃ + +
 *        ┗━┓   ┏━┛
 *          ┃   ┃
 *          ┃   ┃ + + + +
 *          ┃   ┃    Code is far away from bug with the animal protecting
 *          ┃   ┃ +     神兽保佑,代码无bug
 *          ┃   ┃
 *          ┃   ┃  +
 *          ┃    ┗━━━┓ + +
 *          ┃        ┣┓
 *          ┃        ┏┛
 *          ┗┓┓┏━┳┓┏┛ + + + +
 *           ┃┫┫ ┃┫┫
 *           ┗┻┛ ┗┻┛+ + + +
 *
 * @author chenxi
 * @date 2024年6月8日10:12:53
 */

参考:HAR-共享包-应用程序包基础知识-开发基础知识-入门 | 华为开发者联盟 (huawei.com)

相关文章:

OpenHarmony napi 编译 .so 并打包成 .har

一、前言 最近在搞公司标准产品适配OpenHarmony 平台, 按照行业上的常用方法,在Android 是将底层代码用c 封装成 xxx.so ,然后将其他一部分打包成 xxx.jar。 因此,在OpenHarmony 平台也是打算按照这个模式。正所谓,好…...

python 循环导入(circular imports)解决方法

在 Python 中,大部分人都应该都遇到过循环导入的问题。 循环导入是指两个文件各自尝试导入另一个文件(模块),当一个模块没有完全初始化时会导致失败。解决这种情况的最好方法是将代码分层组织,这样导入的关系就会自然…...

01、Linux网络设置

目录 1.1 查看及测试网络 1.1.1 查看网络配置 1、查看网络接口地址 2、查看主机状态 3、查看路由表条目 4、查看网络连接qing 1.1.2 测试网络连接 1.测试网络连接 2.跟踪数据包的路由路径 3.测试DNS域名解析 1.2 设置网络地址参数 1.2.1 使用网络配置命令 1.修改网卡…...

ssm160基于Java技术的会员制度管理的商品营销系统的设计与实现+vue

商品营销系统计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本商品营销系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理…...

边缘计算网关在智慧厕所远程监测与管理的应用

随着智慧城市建设的不断深入,城市公共设施的智慧化管理成为了提升城市品质和居民生活质量的关键建设。公厕作为城市基础设施的重要组成部分,其管理效率和卫生状况直接影响着市民的日常生活体验。在公厕设施建设背景下,边缘计算网关技术的应用…...

嵌入式linux中设备树使用of函数操作基本方法

各位开发者大家好,今天主要给大家分享一下,如何使用of操作函数,获取对应设备树节点先关的属性信息。 第一:of_find_property函数 of_find_property 函数用于在设备树中查找节点下具有指定名称的属性。如果找到了该属性,可以通过返回的属性结构体指针进行进一步的操作,比…...

10.GLM

智谱AI GLM 大模型家族 最强基座模型 GLM-130B GLM (General Language Model Pretraining with Autoregressive Blank Infilling) 基于自回归空白填充的通用语言模型(GLM)。GLM通过增加二维位置编码并允许以任意顺序预测跨度来改进空白填充预训练&…...

【深度学习】Transformer分类器,CICIDS2017,入侵检测,随机森林、RFE、全连接神经网络

文章目录 1 前言2 随机森林训练3 递归特征消除 RFE Recursive feature elimination4 DNN5 Transformer5.1. 输入嵌入层(Input Embedding Layer)5.2. 位置编码层(Positional Encoding Layer)5.3. Transformer编码器层(T…...

pdf压缩到指定大小的简单方法

压缩PDF文件是许多人在日常工作和学习中经常需要面对的问题。PDF文件因其跨平台、易阅读的特性而广受欢迎,但有时候文件体积过大,会给传输和存储带来不便。因此,学会如何有效地压缩PDF文件,就显得尤为重要。本文将详细介绍几种常见…...

关于FPGA对 DDR4 (MT40A256M16)的读写控制 I

关于FPGA对 DDR4 (MT40A256M16)的读写控制 I 语言 :Verilg HDL EDA工具:ISE、Vivado 关于FPGA对 DDR4 (MT40A256M16)的读写控制 I一、引言二、DDR4的特性(MT40A256M16)(1…...

JavaWeb_SpringBootWeb案例

环境搭建: 开发规范 接口风格-Restful: 统一响应结果-Result: 开发流程: 第一步应该根据需求定义表结构和定义接口文档 注意: 本文代码从上往下一直添加功能,后面的模块下的代码包括前面的模块&#xff0c…...

Linux中FTP安装

文章目录 一、FTP介绍1.1、FTP是什么1.2、FTP的工作原理1.3、FTP的传输模式1.4、FTP用户类别1.5、FTP的优点与缺点1.6、FTP数据传输格式 二、FTP客户端与服务端2.1、服务端2.2、客户端 三、FTP服务器软件介绍3.1、WU-FTPD3.2、ProFtpD3.3、vsftpd3.4、Pure-FTP3.5、FileZilla S…...

【Spring EL<二>✈️✈️ 】SL 表达式结合 AOP 注解实现鉴权

目录 🍻前言 🍸一、鉴权(Authorization) 🍺二、功能实现 2.1 环境准备 2.2 代码实现 2.3 测试接口 🍹三、测试功能 3.1 传递 admin 请求 ​ 3.2 传递普通 user 请求 🍻四、章末 &a…...

冯喜运:6.13美盘外汇黄金原油趋势分析及操作策略

【黄金消息面分析】:美国5月生产者价格指数(PPI)的意外下降,为市场带来了通胀可能见顶的积极信号。与此同时,初请失业金人数的上升,为劳动力市场的现状增添了一层不确定性。美国劳工统计局公布的数据显示&a…...

Lecture2——最优化问题建模

一,建模 1,重要性 实际上,我们并没有得到一个数学公式——通常问题是由某个领域的专家口头描述的。能够将问题转换成数学公式非常重要。建模并不是一件容易的事:有时,我们不仅想找到一个公式,还想找到一个…...

unidbg讲解V1

前言 unidbg是什么? unidbg是一个Java项目,可以帮助我们去模拟一个安卓或IOS设备,用于去执行so文件中的算法,从而不需要再去逆向他内部的算法。最终会产出一个jar包,可以被python进行调用。 如何使用unidbg? 下载github上开源的项目:https://github.com/zhkl0228/un…...

软设之敏捷方法

敏捷方法的总体目标是通过尽可能早地,持续地对有价值的软黏的交付,使客户满意 适用于:小步快跑的思想,适合小项目小团队 极限编程XP 4大价值观: 沟通 简单 反馈 勇气 5大原则 快速反馈 简单性假设 逐步修改…...

【设计模式深度剖析】【7】【行为型】【观察者模式】

👈️上一篇:中介者模式 设计模式-专栏👈️ 文章目录 观察者模式英文原文直译如何理解? 观察者模式的角色类图代码示例 观察者模式的应用观察者模式的优点观察者模式的缺点观察者模式的使用场景 观察者模式 观察者模式(Observer…...

列表的C++实

自动扩容 List item 扩容基数为2 可以设置扩容因子&#xff08;这里我没有设置&#xff09; 代码实现如下: // // Created by shaoxinHe on 2024/6/4. //#ifndef CPRIMER_MYLIST_H #define CPRIMER_MYLIST_H#include <stdexcept> #include <vector>namespace st…...

Chisel入门——在windows系统下部署Chisel环境并点亮FPGA小灯等实验

Chisel入门——在windows系统下部署Chisel环境并点亮FPGA小灯等实验 一、chisel简介二、vscode搭建scala开发环境2.1 安装Scala官方插件2.2 java版本&#xff08;本人用的是jdk18&#xff09;2.3 下载Scala Windows版本的二进制文件2.4 配置环境变量2.5 scala测试2.6 vscode运行…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...