openharmony 南向开发基础:ohos自定义子系统,自定义部件,调用hilog部件,hilog日志封装傻瓜式教程

openharmony 南向开发基础:ohos自定义子系统,自定义部件,调用hilog部件,hilog日志封装

自定义单部件

关于开源鸿蒙的南向教程不多,很多都是从官方文档上抄的的例子,官网的例子不是很适合入门,写的很粗糙,不适合傻瓜阅读,毕竟对于刚入行鸿蒙的新手而言,gn语法就是第一劝退魔咒,且openharmony使用的是ohos自定义gn模板,想先自学gn语法再学鸿蒙的话那得猴年马月了,说一千道一万不如实战干一干,会不会骑马你先找匹马上了再说,摔不死就会了
下面给出官网范例以及相应的视频讲解

  1. 官网文档subsys-build-component.md
  2. 视频讲解

看完上面的视频聪明的你应该能抄出一个应用程序,一个动态库,并且使用应用程序引用动态库
上面的例子基于同一个部件,应用程序跟动态库属于同一部件的两个模块,动态库的调用属于部件内调用
上面例子的局限在于,动态库(so库)没有导出部件间接口,即动态库跟exe同属一个部件,其他部件无法使用ohos推荐的gn语法调用so库,但是可以用传统意义上的C++编译规则,获取编译生成的so库和头文件加入到你的部件中,进行手动链接

自定义多部件

为了客服上述单部件创建的so库无法被另一部件gn模板调用的问题,本章节讲解如何使用部件间依赖
首先用白话描述下几个关键名词

  1. 子系统:子系统是一个逻辑上的概念,是鸿蒙模块化构建的第一层,由若干个部件组成,在形式上表现为一个子系统文件夹内部有多个部件文件夹,子系统目录的位置一般为源码根目录,在//build/subsystem_config.json 中可以增删编辑你需要的子系统
  2. 部件:部件是一个构建上的概念,在构建的时候需要提供部件的标志性文件bundle.json,即哪个文件夹内有一个bundle.json就表示这个文件夹内定义了一个部件
  3. 模块:模块是更细层面的构建概念,一个部件由若干个模块组成,每个模块在gn构建语法中体现为一个构建目标target

构建流程

构建的命令形如: ./build.sh --product-name 产品名 --ccache --no-prebuilt-sdk
在使用命令进行源码构建的时候会读取//build/subsystem_config.json中的配置(//表示源码根目录),只有在该文件中配置的子系统才会参与构建,构建的命令中出现了产品名,说明会读取//vendor目录下指定产品的config.json文件,该文件中指明了产品需要的子系统中的那些部件,因此想自定义一个部件参与编译至少需要三步

  1. //build/subsystem_config.json中添加子系统
  2. config.json中添加待编译的子系统部件
  3. 创建自定义部件

创建部件

首先在源码根目录下创建一个文件夹作为逻辑上的子系统,如这里创建一个文件夹为sample,路径为 //sample 即跟//build目录同级
在sample文件夹下创建三个目录:hello , self_share , self_static,分别表示三个部件
hello文件夹是exe部件,self_share是so库部件,self_static是a库部件
参照上面视频教程中的目录结构,在三个目录中分别创建如下结构目录
sample
| ____hello
| ____|____include
| ____| ____|____helloworld.h
| ____| ____|____selfhilog.h
| ____|____src
| ____| ____|____helloworld.cpp
| ____|____BUILD.gn
| ____|____bundle.json
|
| ____self_share
| ____|____include
| ____| ______|____selfshare.h
| ____|
| ____|____src
| ____| _____|____selfshare.cpp
| ____|____BUILD.gn
| ____|____bundle.json
|
| ____self_static
| ____|____include
| ____| ______|____selfshare.h
| ____|
| ____|____src
| ____| ____|____selfshare.cpp
| ____|____BUILD.gn
| ____|____bundle.json
根据目录很清晰可知,hello , self_share , self_static三个目录下均有bundle.json文件,表示这三个目录分别定义了三个部件

  1. 为什么要定义成部件呢?
    在鸿蒙南向开发中,最基本的技能就是掌握部件的构建以及部件相互之间的调用,开发中的难点是如何理解部件并调用开源代码中的系统部件,为了便于快速上手,本范例提供了系统部件hilog调用,自定义一个自动安装的系统部件,一个so库部件模板,一个a库部件模板.
  2. a库(静态库)为什么要定义成部件呢?
    从正式开发上来说,a库一般作为部件内模块,不会单独作为部件提供,因为a库的特性从本质上讲就是源码,编译链接期间会编译进宿主程序,一般会把common,utils等工具类公共类的代码编译为a库,供同部件下其他程序链接使用,但是作为练习教程来讲,C++的三板斧,exe,so,a不能不讲
hello部件

hello部件作为最基础全面的入门部件,本范例提供的hello部件拥有如下功能:

  • 基本的exe部件构建
  • 调用系统部件hilog,封装hilog日志打印
  • 调用self_share部件so库
  • 调用self_static部件a库
基本的exe部件构建

构建一个exe部件的最基础文件为一个.h,一个.cpp,一个.gn,一个.json,上述目录中的selfhilog.h是封装的hilog,本节暂且不提
.h文件如下:

#ifndef HELLOWORLD_H
#define HELLOWORLD_H
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
void HelloPrint();
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif  // HELLOWORLD_H

.cpp文件如下:

#include <stdio.h>
#include "helloworld.h"
int main(int argc, char ** argv) {HelloPrint();return 0;
}
void HelloPrint() {printf("\n\n##################################");printf("\n\tHello G!\n");printf("\n\n----------------------------------\n");
}

.gn文件内容如下:

import("//build/ohos.gni")   #导入编译模板
ohos_executable("helloworld") {  #可执行模块sources = [   #模块源码"src/helloworld.cpp"]include_dirs = [ #模块依赖头文件目录"include"]cflags = []cflags_c = []cflags_cc = []ldflags = []configs = []deps = []             #部件内部依赖external_deps = []    #部件间依赖part_name = "hello"   #所属部件名称,必选install_enable = true #是否默认安装(缺省默认不安装),可选
}

.json文件内容如下:

{"name": "@ohos/hello",		                     "description": "Hello world example",		               "version": "3.1.0",			                          "license": "Apache License 2.0",			          "publishAs": "code-segment",		                    "segment": {				"destPath": "sample/hello"},					                                      "dirs": {},	               "scripts": {},			                                 "component": {			                                 "name": "hello",			                    "subsystem": "sample",		                            "syscap": [],				                        "features": [],                                      "adapted_system_type": ["standard"],		                    "rom": "",                                       "ram": "",                                       "deps": {          "components": [],"third_party": []},  "build": {				                            "sub_component": ["//sample/hello:helloworld" ],			                                  "inner_kits": [],						     "test": []							     }}}

.h跟.ccp文件太基础了就不提了,.gn文件跟.json文件是重点
gn文件描述的是编译的最小target,也就是上面说的模块,gn里面使用了ohos的自定义模板ohos_executable;该函数表示构建一个exe程序,gn文件中最重要的是part_name,该字段表示整个gn文件中的模块属于哪一个部件
json文件描述的是一个部件,segment -> destPath写入你的部件源码目录, component-> name 写入你的部件名字,component-> subsystem 写入当前部件所属的子系统,上面讲了,一个部件可以拥有若干个子模块,如何表示若干个子模块呢?在build->sub_component 中加入你的部件拥有的子模块 形如 子部件目录d:模块名字name,编译的时候会去子部件目录d寻找gn文件,去gn文件中找到名为name的编译模块
需要注意的是,gn中的part_name一定要跟 json中的component-> name 部件名一致

调用系统部件hilog,封装hilog日志打印

上述目录结构中的selfhilog.h 即为封装hilog日志打印,文件内容如下:

#ifndef OHOS_SELFHILOG_LOG_H
#define OHOS_SELFHILOG_LOG_H
#include <cstring>
#include <string>
#include <unistd.h>
#include "hilog/log.h"
#ifndef SELFHILOG_LOG_TAG
#define SELFHILOG_LOG_TAG "SelfHilog"
#endif
#define FILENAME (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
#define SELFHILOG_LOG_DOMAIN   0xD00D521  
static constexpr OHOS::HiviewDFX::HiLogLabel SELFHILOG_LOG_LABEL = {LOG_CORE, SELFHILOG_LOG_DOMAIN, SELFHILOG_LOG_TAG};
#define SELFHILOG_HILOG_PRINT(Level, fmt, ...)                                                                 \(void)OHOS::HiviewDFX::HiLog::Level(SELFHILOG_LOG_LABEL, "%{public}d [%{public}s:%{public}d] " fmt, gettid(), FILENAME, \__LINE__, ##__VA_ARGS__)
#define SELFHILOG_LOGE(fmt, ...) SELFHILOG_HILOG_PRINT(Error, fmt, ##__VA_ARGS__)
#define SELFHILOG_LOGI(fmt, ...) SELFHILOG_HILOG_PRINT(Info, fmt, ##__VA_ARGS__)
#define SELFHILOG_LOGD(fmt, ...) SELFHILOG_HILOG_PRINT(Debug, fmt, ##__VA_ARGS__)
#endif // OHOS_SELFHILOG_LOG_H

因为篇幅原因我删除了所有空行,看起来有点紧凑了,关于hilog的原始用法善用百度,这块教程很多,关于封装部分就是SELFHILOG_HILOG_PRINT这个宏函数,如何看懂这个宏函数?
首先看宏函数参数,一共有三 Level, fmt, …

  1. 参数 Level,宏函数中参数是直接替换的,这个Level会被替换为你传入的字面值,如下面SELFHILOG_LOGE的定义,传入的Level为Error,那么函数体其实就是直接调用Hilog::Error函数
  2. 参数 fmt, ... 这俩是表示格式化输入的不定参数,fmt表示格式, … 表示输入的参数 , SELFHILOG_HILOG_PRINT的函数体参数 "%{public}d [%{public}s:%{public}d] " fmt 这是一个参数位置,C++函数中以逗号分隔一个参数, "%{public}d [%{public}s:%{public}d] " fmt 表示的是一个由两部分拼接而成字符串语句, gettid(), FILENAME, __LINE__ 三个值分别填入第一部分 "%{public}d [%{public}s:%{public}d] ",##__VA_ARGS__ 表示…可变参数,按格式填入第二部分fmt
    因为使用了Hilog部件提供的hilog日志接口,那么在哪里依赖hilog的库以及头文件呢?
    deps = []             #部件内部依赖external_deps = [   "c_utils:utils","hilog:libhilog",]   #部件间依赖part_name = "hello"   #所属部件名称,必选

答案是在gn文件的external_deps中,依赖的形式为 部件名:模块名
除此之外还需要在json文件中添加如下内容:

    "deps": {            "components": ["hilog","c_utils"],"third_party": []}, 

修改以上两部分即可跨部件使用另外部件中的模块了
根据C++的规则,使用第三方so库有两种方式: vs studio演示动态库的两种调用方式1 vs studio演示动态库的两种调用方式2

  1. so库文件 , so库头文件(显式加载,通过获取函数地址指针来调用so库中的函数)
  2. so库文件,so库头文件,so库函数地址导入库.a文件(隐式加载,通过so函数导入库.a文件得到so库函数地址来调用so库中的函数)
    不管使用哪种方式,我们都需要使用so库头文件,在selfhilog.h文件中确实 #include "hilog/log.h",但是有没有注意到一点,我们并没有在hello项目中手动指出 hilog/log.h的文件位置,那么编译器从哪里找到的头文件位置呢? 这个疑问先按下不表,接着看下面内容
调用self_share部件so库

调用自定义部件库的前提是你得有这个部件库,下面就先创建这个部件库
创建一个最简单的so部件库只需四个文件,跟上面创建exe一样
.h文件

#ifndef _SELFSHARE_H_
#define _SELFSHARE_H_
#ifdef __cplusplus
extern "C" {
#endif
void selfshared_helloword(void);
#ifdef __cplusplus
}
#endif
#endif //_SELFSHARE_H_

.cpp文件

#include "selfshare.h"
#include <stdio.h>
void selfshared_helloword(void)
{printf("selfshare say : hello world \n");
}

.gn文件

import("//build/ohos.gni")   #导入编译模板
config("libselfshare_helloworld_config") {visibility = [ ":*" ]include_dirs = [ "include" ]
}
ohos_shared_library("selfshare_helloworld") {  #可执行模块sources = [   #模块源码"src/selfshare.cpp"]public_configs = [ ":libselfshare_helloworld_config" ]#all_dependent_configs 逐层递归传递变量        查看帮助gn all_dependent_configs --helpcflags = []cflags_c = []cflags_cc = []ldflags = []configs = []deps = []             #部件内部依赖external_deps = []part_name = "self_share"   #所属部件名称,必选
}

.json文件

{"name": "@ohos/self_share",		                         "description": "share lib",		                   "version": "3.1.0",			                              "license": "Apache License 2.0",			              "publishAs": "code-segment",		                        "segment": {						"destPath": "sample/self_share"},					                                          "dirs": {},	                   "scripts": {},			                                     "component": {			                                     "name": "self_share",			                        "subsystem": "sample",		                                "syscap": [],				                            "features": [],                                          "adapted_system_type": ["standard"],		                        "rom": "",                                           "ram": "",                                           "deps": {              "components": [],"third_party": []},  "build": {				                                "sub_component": ["//sample/self_share:selfshare_helloworld"],			                                      "inner_kits": [{"name": "//sample/self_share:selfshare_helloworld","header": {"header_files": ["selfshare.h"],"header_base": "//sample/self_share/include"}}   ],						         "test": []							         }}}

.h跟.cpp文件就不说了,这里的关键是.gn跟.json文件

  1. 相比于上文创建一个exe,这里用的是 ohos_shared_library()函数模板创建一个动态库,跟上文的gn文件不同在于,这里使用了两个新函数,config()public_configs()来代替 include_dirs包含头文件目录,public_configs()函数的作用是将当前模块的头文件目录暴露给直接链接当前模块的模块,有点绕,白话就是如果一个exe依赖链接了这个库,那么这个库的头文件目录会自动暴露给这个exe,好了到这里应该能明白为什么上面链接使用hilog库却没有手动包含hilog头文件路径了么,答案就是使用了 public_configs()函数,但是这个函数仅仅能对一个exe的直接依赖链接暴露文件路径,无法对嵌套依赖链接暴露,啥意思呢?
    有一个库叫A.so,A依赖链接了hilog, 现在有个B.exe,B依赖链接了A.so,现在存在两层依赖, A直接依赖hilog,B直接依赖A,如果想在B中使用hilog的原生接口是无法找到hilog的头文件的,因为B不是直接依赖hilog库,public_configs()函数无法嵌套暴露包含的路径,那么有没有办法嵌套暴露呢?答案是使用 all_dependent_configs函数,当然了我这里并不打算演示因为演示的篇幅太长了,再写下去就跟写书一样了,各位学会了这篇的内容可以自行验证
  2. 这里的json文件内容也跟上面创建exe不一样,这里多使用了build->inner_kits,这个字段用于告诉gn,inner_kits里面的内容需要对别的部件暴露,方便别的部件使用部件间依赖使用本部件的模块,name字段写模块的名字(需使用全路径),header_files写需要暴露的头文件,header_base写header_files中头文件的位置
    调用本部件的方法跟上文调用hilog的方法一样,需要在gn文件的external_deps中添加 本部件:模块,在json文件的deps->components添加本部件
调用self_static部件a库

a库(静态链接库)的构建方式跟so库基本一致,唯一不一样的是ohos的创建函数模板,a库使用 ohos_static_library()函数模板
.h

#ifndef _SELFSTATIC_H_
#define _SELFSTATIC_H_
#ifdef __cplusplus
extern "C" {
#endif
void selfstatic_helloword(void);
#ifdef __cplusplus
}
#endif
#endif //_SELFSTATIC_H_

.cpp

#include "selfstatic.h"
#include <stdio.h>
void selfstatic_helloword(void)
{printf("selfstatic say : hello world \n");
}

.gn

import("//build/ohos.gni")
config("libselfstatic_helloworld_config") {visibility = [ ":*" ]include_dirs = [ "include" ]
}
ohos_static_library("selfstatic_helloworld"){sources = ["src/selfstatic.cpp"]public_configs = [ ":libselfstatic_helloworld_config" ]deps = []part_name = "self_static"
}

.json

{"name": "@ohos/self_static",		                         "description": "static lib",		                   "version": "3.1.0",			                              "license": "Apache License 2.0",			              "publishAs": "code-segment",		                        "segment": {						"destPath": "sample/self_static"},					                                          "dirs": {},	                   "scripts": {},			                                     "component": {			                                     "name": "self_static",			                        "subsystem": "sample",		                                "syscap": [],				                            "features": [],                                          "adapted_system_type": ["standard"],		                        "rom": "",                                           "ram": "",                                           "deps": {              "components": [],"third_party": []},  "build": {				                                "sub_component": ["//sample/self_static:selfstatic_helloworld"],			                                      "inner_kits": [{"name": "//sample/self_static:selfstatic_helloworld","header": {"header_files": ["selfstatic.h"],"header_base": "//sample/self_static/include"}}   ],								         "test": []							         }}}

调用本部件的方法跟上文调用so库的方法一样,需要在gn文件的external_deps中添加 本部件:模块,在json文件的deps->components添加本部件

编译部件

上面的内容创建了三个部件,在链接了自定义的so库跟a库后,exe的gn文件如下:

import("//build/ohos.gni")   #导入编译模板
ohos_executable("helloworld") {  #可执行模块sources = [   #模块源码"src/helloworld.cpp"]include_dirs = [ #模块依赖头文件目录"include"]cflags = []cflags_c = []cflags_cc = []ldflags = []configs = []deps = [ ]             #部件内部依赖external_deps = [   "c_utils:utils","hilog:libhilog","self_share:selfshare_helloworld","self_static:selfstatic_helloworld"]part_name = "hello"   #所属部件名称,必选install_enable = true #是否默认安装(缺省默认不安装),可选
}

exe的json文件如下:

{"name": "@ohos/hello",		                         "description": "Hello world example",		                   "version": "3.1.0",			                              "license": "Apache License 2.0",			              "publishAs": "code-segment",		                        "segment": {						"destPath": "sample/hello"},					                                          "dirs": {},	                   "scripts": {},			                                     "component": {			                                     "name": "hello",			                        "subsystem": "sample",		                                "syscap": [],				                            "features": [],                                          "adapted_system_type": ["standard"],		                        "rom": "",                                           "ram": "",                                           "deps": {              "components": ["hilog","c_utils","self_share","self_static"],"third_party": []},  "build": {				                                "sub_component": ["//sample/hello:helloworld" ],			                                      "inner_kits": [],						         "test": []							         }}}

不知道聪明的你有没有写对呢
在上面构建流程章节已经讲过想自定义一个部件参与编译至少需要三步,下面将本次创建的三个部件添加编译

  1. 在//build/subsystem_config.json中添加如下内容:
  "sample": {"path": "sample","name": "sample"}

参照subsystem_config.json中其他子系统的添加方式,注意书写格式
该内容表示添加一个子系统sample, 路径就是根目录sample目录,子系统的名字就是sample
2. /vendor/厂家/产品名/config.json中添加如下内容:

{"subsystem": "sample","components": [{"component": "hello","features": []},{"component": "self_share","features": []},{"component": "self_static","features": []}  ]
}

参照config.json中其他模块的添加方式,注意书写格式
该内容表示将子系统sample下的hello,self_share,self_static三个部件加入到产品构建当中
3. 编译部件
新增的部件有两种构建思路:

  • 单部件构建 : ./build.sh --product-name 产品名 -T helloworld --ccache --no-prebuilt-sdk
  • 全量构建 : ./build.sh --product-name 产品名 --ccache --no-prebuilt-sdk

单部件构建:直接构建helloworld模块,还记得上面说的,模块是最小编译target,可以直接进行指定编译,编译helloworld模块会把依赖项hilog,selfshare_helloworld,selfstatic_helloworld全部编译;在//out目录下查找helloworld跟libselfshare_helloworld.so

find ./ -name "helloworld"
find ./ -name "*selfshare_helloworld*"

将这两个文件上传到板子

hdc file send XXXXXXXX/helloworld  /bin/
hdc file send XXXXXXXX/libselfshare_helloworld.so  /lib64/

因为a库被编译到helloworld中了,所以只要拷贝俩文件就行
在板子上赋予helloworld执行权限,执行helloworld
全量构建:将整个源码编译,做成镜像烧录到开发板,通过hdc链接开发板可以直接运行helloworld,因为我们在gn文件中标记了install_enable = true默认安装
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue 路由用法 router-view

通过router-view 点击子路由显示子路由关于我们的内容&#xff0c;点击关于信息显示关于信息内容。

map/set和unordered_map/unordered_set的区别及使用情况

map/set和unordered_map/unordered_set的区别 容器底层数据结构是否有序实现版本复杂度迭代器map/set红黑树有序C98O(logN&#xff09;双向迭代器unordered_map/unordered_set哈希表/散列表无序C11O(1)单向迭代器 unordered_set无序的&#xff08;VS下&#xff09; void uno…

【机器学习】探索数据矿藏:Python中的AI大模型与数据挖掘创新实践

&#x1f496; 前言&#xff1a;探索数据矿藏1. &#x1f4ca;数据获取与预处理&#xff1a;AI大模型的燃料1.1 &#x1f310;数据获取&#xff1a;多样性与规模并重1.2 &#x1f9f9;数据清洗与处理&#xff1a;提升数据质量1.3 &#x1f50d;特征工程&#xff1a;挖掘数据的深…

蓝牙音视频远程控制协议(AVRCP) command跟response介绍

零.声明 本专栏文章我们会以连载的方式持续更新&#xff0c;本专栏计划更新内容如下&#xff1a; 第一篇:蓝牙综合介绍 &#xff0c;主要介绍蓝牙的一些概念&#xff0c;产生背景&#xff0c;发展轨迹&#xff0c;市面蓝牙介绍&#xff0c;以及蓝牙开发板介绍。 第二篇:Trans…

[Qt][QSS][下]详细讲解

目录 1.样式属性0.前言1.盒模型(Box Model) 2.常用控件样式属性1.按钮2.复选框3.单选框4.输入框5.列表6.菜单栏7.注意 1.样式属性 0.前言 QSS中的样式属性⾮常多&#xff0c;不需要都记住&#xff0c;核⼼原则是⽤到了就去查 ⼤部分的属性和CSS是⾮常相似的 QSS中有些属性&am…

稚晖君发布5款全能人形机器人,开源创新,全能应用

8月18日&#xff0c;智元机器人举行“智元远征 商用启航” 2024年度新品发布会&#xff0c;智元联合创始人彭志辉主持并发布了“远征”与“灵犀”两大系列共五款商用人形机器人新品——远征A2、远征A2-W、远征A2-Max、灵犀X1及灵犀X1-W&#xff0c;并展示了在机器人动力、感知、…

爱心商城系统pf

TOC springboot424爱心商城系统pf 第1章 绪论 1.1 课题背景 二十一世纪互联网的出现&#xff0c;改变了几千年以来人们的生活&#xff0c;不仅仅是生活物资的丰富&#xff0c;还有精神层次的丰富。在互联网诞生之前&#xff0c;地域位置往往是人们思想上不可跨域的鸿沟&…

在亚马逊云科技上安全、合规地创建AI大模型训练基础设施并开发AI应用服务

项目简介&#xff1a; 小李哥将继续每天介绍一个基于亚马逊云科技AWS云计算平台的全球前沿AI技术解决方案&#xff0c;帮助大家快速了解国际上最热门的云计算平台亚马逊云科技AWS AI最佳实践&#xff0c;并应用到自己的日常工作里。 本次介绍的是如何在亚马逊云科技利用Servi…

Mac电脑虚拟机安装win11教程

Mac分享吧 文章目录 效果一、准备工作二、安装步骤方法1&#xff1a;使用虚拟机自带的win11系统&#xff0c;选中系统软件--继续--安装&#xff0c;即可完成win11安装方法2&#xff1a;通过下载好的镜像安装Windows11系统。选择镜像文件位置&#xff0c;安装&#xff0c;配置1…

前后端项目交互异步请求JSON数据类型后端标准响应数据格式

java同步请求 当网页与后端交互时,前端不能再进行其他操作 服务器响应回来的内容,会把整个浏览器中的内容覆盖 这种请求方式在前后端交互时不太友好 现在的前后端交互请求都使用异步请求 异步请求(不同步) 通过在前端中使用js中提供的XMLHttpRequest对象实现发送异步请求…

算法的学习笔记—二叉树的镜像(牛客JZ27)

&#x1f600;前言 在二叉树相关的问题中&#xff0c;镜像操作是一个非常经典且常见的题目。本文将通过一道具体的题目&#xff0c;详细讲解如何将一棵二叉树转换为它的镜像&#xff0c;并提供实现该操作的Java代码示例。 &#x1f3e0;个人主页&#xff1a;尘觉主页 文章目录 …

CRNN不定长验证码识别

原文:CRNN不定长验证码识别 - 知乎 (zhihu.com) 一、不定长验证码识别 关于验证码识别的任务,我们可以通过使用卷积神经网络采用多标签分类的方法来完成,但是当验证码是不定长的时候,就无法使用多标签分类的方法来解决了,在这类任务中,识别的目标是类似于序列的长条形图…

React原理之Fiber详解

前置文章&#xff1a; React原理之 React 整体架构解读React原理之整体渲染流程 -----读懂这一篇需要对 React 整体架构和渲染流程有大致的概念 &#x1f60a;----- 在React原理之 React 整体架构解读中&#xff0c;简单介绍了 Fiber 架构&#xff0c;也了解了 Fiber 节点的…

IT服务标准化知识体系攻略(至简)

标准是为了在一定范围内获得最佳秩序 &#xff0c;经协商一致制定并由公开机构批准共同使用和重复使用的和中规范性文件。标准是标准化活动的主要成果之一。国家标准的制定有一套正常程序&#xff0c;分为预阶段、立项阶段、起草阶段、征求意见阶段、审查阶段、批准阶段、出版阶…

88.SAPUI5 Model Binding的问题-在view更改数据,model却不变

目录 1.背景 2.sap.ui.model.BindingMode sap.ui.model.BindingMode.OneWay sap.ui.model.BindingMode.TwoWay 3.oModel.setDefaultBindingMode 方法说明 execOneWay方法 execTwoWay方法 1.背景 在做一个UI5项目&#xff0c;后台读取sap.ui.model.Model后&#xff0c;把…

C++高性能编程:ZeroMQ vs Fast-DDS发布-订阅模式下性能对比与分析

文章目录 0. 引言1. 目标&#xff1a;ZeroMQ与Fast-DDS性能对比2. ZeroMQ vs Fast-DDS - 延迟基准测试2.1 一对一发布-订阅延迟2.2 一对多发布-订阅延迟 3. ZeroMQ vs Fast-DDS - 吞吐量基准测试4. 方法论5. 结论6. 参考 0. 引言 高要求的分布式系统催生了对轻量级且高性能中间…

C++:命名空间与输入输出

目录 前言 一、命名空间 1.1 namespace的价值 1.2 namespace的定义 1.3 命名空间的使用 二、C输入&输出 前言 C是一种面向对象的计算机程序设计语言&#xff0c;‌它扩展了C语言的功能&#xff0c;‌并引入了面向对象编程的概念&#xff0c;‌如类、‌继承和多态等&a…

【图形学】TA之路-矩阵应用平移-旋转-大小

矩阵应用&#xff1a;在 Unity 中&#xff0c;Transform 和矩阵之间的关系非常密切。Transform 组件主要用于描述和控制一个物体在三维空间中的位置、旋转和缩放&#xff0c;而这些操作背后实际上都是通过矩阵来实现的 1. Transform 组件与矩阵的关系 Transform 组件包含以下…

基于django的影音播放网站 /基于python的影视网站/影视播放系统

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&a…

论文阅读笔记:The Graph Neural Network Model

论文来源 IEEE Transactions on Neural Networks&#xff0c;Volume: 20 Issue: 1 背景 图神经网络模型本身具有广泛的使用背景&#xff0c;由于我个人研究交通流量预测的需要&#xff0c;此处仅考虑深度学习领域。图结构指的是由节点node和若干个连接的边edge组成的一种数据…