OpenHarmony子系统开发 - Rust编译构建指导

OpenHarmony子系统开发 - Rust编译构建指导

一、Rust模块配置规则和指导

概述

Rust是一门静态强类型语言,具有更安全的内存管理、更好的运行性能、原生支持多线程开发等优势。Rust官方也使用Cargo工具来专门为Rust代码创建工程和构建编译。 OpenHarmony为了集成C/C++代码和提升编译速度,使用了GN + Ninja的编译构建系统。GN的构建语言简洁易读,Ninja的汇编级编译规则直接高效。 为了在OpenHarmony中集成Rust代码,并最大程度发挥Rust和OpenHarmony中原有C/C++代码的交互性,采用GN作为统一构建工具,即通过GN构建Rust源码文件(xxx.rs),并增加与C/C++互操作、编译时lint、测试、IDL转换、三方库集成、IDE等功能。同时扩展gn框架,支持接口自动化转换,最大程度简化开发。

基本概念

术语描述
CargoCargo是Rust官方使用的构建工具,允许Rust项目声明其各种依赖项,并确保您始终获得可重复的构建。
cratecrate是一个独立的可编译单元。
LintLint是指出常见编程错误、错误、样式错误和可疑结构的工具。可以对程序进行更加广泛的错误分析。

配置规则

OpenHarmony提供了用于Rust代码编译构建的各类型GN模板,可以用于编译Rust可执行文件,动态库和静态库等。各类型模板说明如下:

GN模板功能输出
ohos_rust_executablerust可执行文件rust可执行文件,不带后缀
ohos_rust_shared_libraryrust动态库rust dylib动态库,默认后缀.dylib.so
ohos_rust_static_libraryrust静态库rust rlib静态库,默认后缀.rlib
ohos_rust_proc_macrorust proc_macrorust proc_macro库, 默认后缀.so
ohos_rust_shared_ffirust FFI动态库rust cdylib动态库,给C/C++模块调用,默认后缀.so
ohos_rust_static_ffirust FFI静态库rust staticlib库,给C/C++模块调用,默认后缀.a
ohos_rust_cargo_crate三方包Cargo craterust三方crate,支持rlib、dylib、bin
ohos_rust_systemtestrust系统测试用例rust可执行系统测试用例,不带后缀
ohos_rust_unittestrust单元测试用例rust可执行单元测试用例,不带后缀
ohos_rust_fuzztestrust Fuzz测试用例rust可执行Fuzz测试用例,不带后缀

配置指导

配置Rust模块与C/C++模块类似,参考模块配置规则。下面是使用不同模板的示例。

配置Rust静态库示例

该示例用于测试Rust可执行bin文件和静态库rlib文件的编译,以及可执行文件对静态库的依赖,使用模板ohos_rust_executable和ohos_rust_static_library。操作步骤如下:

  1. 创建build/rust/tests/test_rlib_crate/src/simple_printer.rs,如下所示:

    //! simple_printer/// struct RustLogMessagepub struct RustLogMessage {/// i32: idpub id: i32,/// String: msgpub msg: String,
    }/// function rust_log_rlib
    pub fn rust_log_rlib(msg: RustLogMessage) {println!("id:{} message:{:?}", msg.id, msg.msg)
    }
    
  2. 创建build/rust/tests/test_rlib_crate/src/main.rs,如下所示:

    //! rlib_crate example for Rust.extern crate simple_printer_rlib;use simple_printer_rlib::rust_log_rlib;
    use simple_printer_rlib::RustLogMessage;fn main() {let msg: RustLogMessage = RustLogMessage {id: 0,msg: "string in rlib crate".to_string(),};rust_log_rlib(msg);
    }
    
  3. 配置gn脚本build/rust/tests/test_rlib_crate/BUILD.gn,如下所示:

    import("//build/ohos.gni")ohos_rust_executable("test_rlib_crate") {sources = [ "src/main.rs" ]deps = [ ":simple_printer_rlib" ]
    }ohos_rust_static_library("simple_printer_rlib") {sources = [ "src/simple_printer.rs" ]crate_name = "simple_printer_rlib"crate_type = "rlib"features = [ "std" ]
    }
    
  4. 执行编译得到的可执行文件,运行结果如下:

    test_rlib_crate

配置三方库示例

rust三方库的BUILD.gn文件可通过cargo2gn工具自动生成。参见:Cargo2gn工具操作指导

该示例用于测试包含预编译文件build.rs的三方静态库rlib文件的编译,使用了模板ohos_rust_executable和ohos_rust_cargo_crate。操作步骤如下:

  1. 创建build/rust/tests/test_rlib_cargo_crate/crate/src/lib.rs,如下所示:

    include!(concat!(env!("OUT_DIR"), "/generated/generated.rs"));pub fn say_hello_from_crate() {assert_eq!(run_some_generated_code(), 45);#[cfg(is_new_rustc)]println!("Is new rustc");#[cfg(is_old_rustc)]println!("Is old rustc");#[cfg(is_ohos)]println!("Is ohos");#[cfg(is_mac)]println!("Is darwin");#[cfg(has_feature_a)]println!("Has feature_a");#[cfg(not(has_feature_a))]panic!("Wasn't passed feature_a");#[cfg(not(has_feature_b))]#[cfg(test_a_and_b)]panic!("feature_b wasn't passed");#[cfg(has_feature_b)]#[cfg(not(test_a_and_b))]panic!("feature_b was passed");
    }#[cfg(test)]
    mod tests {/// Test features are passed through from BUILD.gn correctly. This test is the target configuration.#[test]#[cfg(test_a_and_b)]fn test_features_passed_target1() {#[cfg(not(has_feature_a))]panic!("feature a was not passed");#[cfg(not(has_feature_b))]panic!("feature b was not passed");}#[test]fn test_generated_code_works() {assert_eq!(crate::run_some_generated_code(), 45);}
    }
    
  2. 创建build/rust/tests/test_rlib_cargo_crate/crate/src/main.rs,如下所示:

    pub fn main() {test_rlib_crate::say_hello_from_crate();
    }
    
  3. 创建build/rust/tests/test_rlib_cargo_crate/crate/build.rs,如下所示:

    use std::env;
    use std::path::Path;
    use std::io::Write;
    use std::process::Command;
    use std::str::{self, FromStr};fn main() {println!("cargo:rustc-cfg=build_script_ran");let my_minor = match rustc_minor_version() {Some(my_minor) => my_minor,None => return,};if my_minor >= 34 {println!("cargo:rustc-cfg=is_new_rustc");} else {println!("cargo:rustc-cfg=is_old_rustc");}let target = env::var("TARGET").unwrap();if target.contains("ohos") {println!("cargo:rustc-cfg=is_ohos");}if target.contains("darwin") {println!("cargo:rustc-cfg=is_mac");}let feature_a = env::var_os("CARGO_FEATURE_MY_FEATURE_A").is_some();if feature_a {println!("cargo:rustc-cfg=has_feature_a");}let feature_b = env::var_os("CARGO_FEATURE_MY_FEATURE_B").is_some();if feature_b {println!("cargo:rustc-cfg=has_feature_b");}// Some tests as to whether we're properly emulating various cargo features.assert!(Path::new("build.rs").exists());assert!(Path::new(&env::var_os("CARGO_MANIFEST_DIR").unwrap()).join("build.rs").exists());assert!(Path::new(&env::var_os("OUT_DIR").unwrap()).exists());// Confirm the following env var is setenv::var_os("CARGO_CFG_TARGET_ARCH").unwrap();generate_some_code().unwrap();
    }fn generate_some_code() -> std::io::Result<()> {let test_output_dir = Path::new(&env::var_os("OUT_DIR").unwrap()).join("generated");let _ = std::fs::create_dir_all(&test_output_dir);// Test that environment variables from .gn files are passed to build scriptslet preferred_number = env::var("ENV_VAR_FOR_BUILD_SCRIPT").unwrap();let mut file = std::fs::File::create(test_output_dir.join("generated.rs"))?;write!(file, "fn run_some_generated_code() -> u32 {{ {} }}", preferred_number)?;Ok(())
    }fn rustc_minor_version() -> Option<u32> {let rustc_bin = match env::var_os("RUSTC") {Some(rustc_bin) => rustc_bin,None => return None,};let output = match Command::new(rustc_bin).arg("--version").output() {Ok(output) => output,Err(_) => return None,};let rustc_version = match str::from_utf8(&output.stdout) {Ok(rustc_version) => rustc_version,Err(_) => return None,};let mut pieces = rustc_version.split('.');if pieces.next() != Some("rustc 1") {return None;}let next_var = match pieces.next() {Some(next_var) => next_var,None => return None,};u32::from_str(next_var).ok()
    }
    
  4. 配置gn脚本build/rust/tests/test_rlib_cargo_crate/BUILD.gn,如下所示:

    import("//build/templates/rust/ohos_cargo_crate.gni")ohos_cargo_crate("target") {crate_name = "test_rlib_crate"crate_root = "crate/src/lib.rs"sources = [ "crate/src/lib.rs" ]#To generate the build_script binarybuild_root = "crate/build.rs"build_sources = [ "crate/build.rs" ]build_script_outputs = [ "generated/generated.rs" ]features = ["my-feature_a","my-feature_b","std",]rustflags = ["--cfg","test_a_and_b",]rustenv = [ "ENV_VAR_FOR_BUILD_SCRIPT=45" ]
    }# Exists to test the case that a single crate has both a library and a binary
    ohos_cargo_crate("test_rlib_crate_associated_bin") {crate_root = "crate/src/main.rs"crate_type = "bin"sources = [ "crate/src/main.rs" ]#To generate the build_script binarybuild_root = "crate/build.rs"build_sources = [ "crate/build.rs" ]features = ["my-feature_a","my-feature_b","std",]rustenv = [ "ENV_VAR_FOR_BUILD_SCRIPT=45" ]deps = [ ":target" ]
    }
    
  5. 执行编译得到的可执行文件,运行结果如下:

    test_rlib_cargo_crate

其他源码实例

在build/rust/tests目录下有Rust各类型模块的配置实例可供参考:

用例目录测试功能
build/rust/tests/test_bin_crate用ohos_rust_executable模板在host平台编译可执行文件,在target平台上运行可执行文件。
build/rust/tests/test_static_link测试可执行文件对标准库的静态链接。
build/rust/tests/test_dylib_crate测试对动态库的编译和动态链接功能
build/rust/tests/test_rlib_crate测试对静态库的编译和静态链接功能
build/rust/tests/test_proc_macro_crate测试对Rust过程宏的编译和链接功能。提供对不同类型的宏的测试用例。
build/rust/tests/test_cdylib_crate测试将Rust代码编译成C/C++动态库。
build/rust/tests/test_staticlib_crate测试将Rust代码编译成C/C++静态库。
build/rust/tests/rust_test_ut测试Rust代码单元测试模板功能(ability)。
build/rust/tests/rust_test_st测试Rust代码系统测试模板功能(ability)。
build/rust/tests/test_bin_cargo_crate测试Rust三方可执行文件的编译和运行。三方源码中包含build.rs。
build/rust/tests/test_rlib_cargo_crate测试Rust三方静态库的编译和静态链接。三方源码中包含build.rs。
build/rust/tests/test_proc_macro_cargo_crate测试Rust三方过程宏的编译和链接。三方源码中包含build.rs。
build/rust/tests/rust_test_fuzzb测试Rust代码Fuzz测试模板功能。

参考

特性点实例

Rust源码依赖调用C/C++库

OpenHarmony上C/C++模块动态库默认用.z.so后缀,但是Rust的编译命令通过-l链接时,默认只会链接.so后缀的动态库。因此如果要依赖一个C/C++动态库编译模块,需要在该动态库的GN构建文件中添加output_extension = "so"的声明,这样编译得到的动态库将会以".so"作为后缀,而不是".z.so"。 在Rust源码中如果直接链接动态库,后缀也需要使用".so",这时使用动态库的中间名,不需要添加lib前缀。例如Rust源码中链接libhilog.so:

#[link(name = "hilog")]
externs使用

某个模块如果依赖二进制的rlib库,可以使用externs属性:

executable("foo") {sources = [ "main.rs" ]externs = [{                    # 编译时会转成`--extern bar=path/to/bar.rlib`crate_name = "bar"path = "path/to/bar.rlib"}]
}

Lint规则

OpenHarmony框架支持rustc lints和clippy lints两种Lint,每种Lint划为三个等级的标准:"openharmony"、"vendor"和"none",严格程度按照"openharmony" -> "vendor" -> "none"逐级递减。 配置Rust模块时可以通过rustc_lints和clippy_lints来指定使用Lint的等级。 模块中没有配置rustc_lints或者clippy_lints时会根据模块所在路径来匹配lints等级。不同路径下的Rust代码的语法规范会有不同程度地约束,因此用户在OpenHarmony配置Rust代码编译模块时还应关注模块所在路径。

rustc lints和clippy lints的各等级标志
lints类型模块属性lints等级lints等级标志lints内容
rustc_lintsrustc_lintsopenharmonyRustOhosLints"-A deprecated", "-D missing-docs", "-D warnigngs"
rustc_lintsrustc_lintsvendorRustcVendorLints"-A deprecated", "-D warnigs"
rustc_lintsrustc_lintsnoneallowAllLints"-cap-lints allow"
clippy lintsclippy lintsopenharmonyClippyOhosLints"-A clippy::type-complexity", "-A clippy::unnecessary-wraps", "-A clippy::unusual-byte-groupings", "-A clippy::upper-case-acronyms"
clippy lintsclippy lintsvendorClippyVendorLints"-A clippy::complexity", "-A Clippy::perf", "-A clippy::style"
clippy lintsclippy lintsnoneallowAllLints"--cap-lints allow"
代码路径与lints等级的对应关系
路径Lints等级
thirdpartynone
prebuiltsnone
vendorvendor
devicevendor
othersopenharmony

交互工具使用指导

Cargo2gn工具操作指导

二、Rust 工具链使用说明

简介

本文用于指导 Rust 语言开发者编译构建 OpenHarmony OS Rust 应用程序。

Rust 是一门静态强类型语言,具有更安全的内存管理、更好的运行性能、原生支持多线程开发等优势。

本工具链基于开源 rust 与 llvm 增量开发,适配了 OpenHarmony OS target 二进制构建。可将 rust 源码编译成能在 OpenHarmony OS 设备上使用的目标二进制。

使用场景

  • 在 Linux x86环境本地编译 Linux x86 目标二进制或交叉编译 OpenHarmony OS 目标二进制。
  • 在 Mac x86 环境本地编译 Mac x86 目标二进制。
  • 在 Mac arm64 环境本地编译 Mac arm64 目标二进制。

操作指导

OpenHarmony 社区代码编译

  1. 下载或更新环境中 OpenHarmony 社区代码,下载方式可参考获取源码。

  2. 执行源码中脚本下载安装工具链。

    ./build/prebuilts_download.sh
    
  3. 准备待编译代码。

    创建 build/rust/tests/test_bin_crate 目录,目录下新建如下所示文件与文件夹。

    ├── BUILD.gn
    └── src└── main.rs
    

    main.rs 代码示例。

    //! Hello world example for Rust.fn main() {println!("Hello, world!");println!(env!("RUSTENV_TEST"));
    }
    

    BUILD.gn 代码示例。

    import("//build/ohos.gni")ohos_rust_executable("test_bin_crate") {sources = [ "src/main.rs" ]rustenv = [ "RUSTENV_TEST=123" ]features = [ "std" ]if (is_mingw) {rust_static_link = true}
    }
    
  4. 执行编译命令。

    ./build.sh --product-name {product_name} --build-target
    

    以RK3568为例,若要编译,请执行如下命令。

    ./build.sh --product-name rk3568 --build-target build/rust/tests/test_bin_crate:test_bin_crate –no-prebuilt-sdk
    

    编译生成的文件。

    ./out/rk3568/build/build_framework/test_bin_crate
    

非OpenHarmony 社区代码编译

安装 rust 工具链
  1. 下载 build 仓代码。

    git clone git@gitee.com:openharmony/build.git
    
  2. 执行脚本下载安装工具链。

    ./build/prebuilts_download.sh
    
  3. 查看安装情况。

    ./prebuilts/rustc/linux-x86_64/current/bin/rustc --version
    

    有类似如下显示表示安装成功。

    rustc 1.72.0-nightly (xxxx)
    
安装 OpenHarmony OS Clang 工具

icon-note

说明

用于在 Linux x86 环境下进行 OpenHarmony OS 的 target 交叉编译,不编译 OpenHarmony OS target 可不安装。

  1. 在 OpenHarmony 的最新版本说明中获取 SDK 包下载路径

    ohos_sdk_download

  2. 选择 Linux 环境 SDK 包下载,依次解压下载的压缩包。

    mv ohos-sdk-windows_linux-public.tar.gz /opt/
    cd /opt/
    tar -zxvf ohos-sdk-windows_linux-public.tar.gz
    cd ohos-sdk/linux
    unzip native-linux-x64-4.1.7.5-Release.zip
    
编译代码
  1. 代码用例main.rs。

    fn main() {println!("hello world");
    }
    
  2. 编译 target 为本地环境时命令示例。

    ./prebuilts/rustc/linux-x86_64/current/bin/rustc main.rs
    

    执行构建结果。

    ./main
    hello world
    
  3. 编译 target 为 armv7-unknown-linux-ohos时命令示例。

    ./prebuilts/rustc/linux-x86_64/current/bin/rustc main.rs --target=armv7-unknown-linux-ohos -C linker=/opt/ohos-sdk/linux/native/llvm/bin/armv7-unknown-linux-ohos-clang
    
  4. 编译 target 为 aarch64-unknown-linux-ohos时命令示例。

    ./prebuilts/rustc/linux-x86_64/current/bin/rustc main.rs --target=aarch64-unknown-linux-ohos -C linker=/opt/ohos-sdk/linux/native/llvm/bin/aarch64-unknown-linux-ohos-clang
    
  5. 编译 target 为 x86_64-unknown-linux-ohos时命令示例。

    ./prebuilts/rustc/linux-x86_64/current/bin/rustc main.rs --target=x8

三、Cargo2gn工具操作指导

概述

rust三方库使用cargo编译,配置为Cargo.toml。集成到OpenHarmony上需要转换成BUILD.gn规则。为了满足这个需求,需要提供一个cargo2gn转换工具。当需要引入rust三方crate时使用cargo2gn转换工具来把三方库的Cargo.toml转换成BUILD.gn规则。cargo2gn可以单个库进行转换,也可以多个库进行批量转换。

单个库转换操作步骤

  1. 进入到需要转化的rust三方库的目录下,比如需要转化bindgen。

    cd openharmony/third_party/rust/bindgen
    
  2. 创建配置文件cargo2gn.json,可以参考如下配置。

    {"copy-out": true,"run": true,"add-workspace": true,"cargo-bin": "/mnt/xxx/openharmony/prebuilts/rustc/linux-x86_64/current/bin"
    }
    
  3. 执行以下命令进行转换。

    python3 /mnt/xxx/openharmony/build/scripts/cargo2gn.py --config cargo2gn.json
    

    转换结果

    import("//build/templates/rust/ohos_cargo_crate.gni")ohos_cargo_crate("lib") {crate_name = "bindgen"crate_type = "rlib"crate_root = "./lib.rs"sources = ["./lib.rs"]edition = "2018"cargo_pkg_version = "0.64.0"cargo_pkg_authors = "Jyun-Yan You <jyyou.tw@gmail.com>,  Emilio Cobos Álvarez <emilio@crisal.io>,  Nick Fitzgerald <fitzgen@gmail.com>,  The Servo project developers"cargo_pkg_name = "bindgen"cargo_pkg_description = "Automatically generates Rust FFI bindings to C and C++ libraries."deps = ["//third_party/rust/bitflags:lib","//third_party/rust/cexpr:lib","//third_party/rust/clang-sys:lib","//third_party/rust/lazy_static:lib","//third_party/rust/lazycell:lib","//third_party/rust/log:lib","//third_party/rust/peeking_take_while:lib","//third_party/rust/proc-macro2:lib","//third_party/rust/quote:lib","//third_party/rust/regex:lib","//third_party/rust/rustc-hash:lib","//third_party/rust/shlex:lib","//third_party/rust/syn:lib","//third_party/rust/which:lib",]features = ["default","log","logging","static","which","which-rustfmt",]build_root = "build.rs"build_sources = ["build.rs"]build_script_outputs = ["host-target.txt"]
    }
    

多个库批量转换操作步骤

  1. 进入到rust目录下。

    cd openharmony/third_party/rust
    
  2. 把所有需要转换的rust三方库添加到rust目录下的Cargo.toml的[workspace]里,如下所示。

    [workspace]
    members = ["aho-corasick","memchr",
    ]
    
  3. 执行单个库转换操作步骤的2和3。

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

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

相关文章

分享一个免费的CKA认证学习资料

关于CKA考试 CKA&#xff08;Certified Kubernetes Administrator&#xff09;是CNCF基金会&#xff08;Cloud Native Computing Foundation&#xff09;官方推出的Kubernetes管理员认证计划&#xff0c;用于证明持有人有履行Kubernetes管理的知识&#xff0c;技能等相关的能力…

MySQL的一些八股文

1.什么是BufferPool&#xff1f; Buffer Pool基本概念 Buffer Pool&#xff1a;缓冲池&#xff0c;简称BP。其作用是用来缓存表数据与索引数据&#xff0c;减少磁盘IO操作&#xff0c;提升效率。 Buffer Pool由缓存数据页(Page) 和 对缓存数据页进行描述的控制块 组成, 控制…

卷积神经网络(笔记02)

一、简述在卷积神经网络中池化层的作用&#xff0c;并解释其为何能帮助提高模型性能 。 池化层的作用 1. 降低数据维度 池化操作通过对输入特征图进行下采样&#xff0c;减少特征图的空间尺寸。常见的池化方式有最大池化&#xff08;Max Pooling&#xff09;和平均池化&…

面试系列|蚂蚁金服技术面【1】

哈喽&#xff0c;大家好&#xff01;今天分享一下蚂蚁金服的 Java 后端开发岗位真实社招面经&#xff0c;复盘面试过程中踩过的坑&#xff0c;整理面试过程中提到的知识点&#xff0c;希望能给正在准备面试的你一些参考和启发&#xff0c;希望对你有帮助&#xff0c;愿你能够获…

带环链表的相关知识点

带环链表的相关知识点 1.判断是否有环2.寻找入环节点补充&#xff1a;相交链表 如果链表中有某个节点,可以通过连续跟踪next指针再次到达,则链表中存在环。为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&#xff08;索引从 0 开…

初探 Threejs 物理引擎CANNON,解锁 3D 动态魅力

简介 Cannon.js 是一个基于 JavaScript 的物理引擎&#xff0c;它可以在浏览器中模拟物理效果。它支持碰撞检测、刚体动力学、约束等物理效果&#xff0c;可以用于创建逼真的物理场景和交互。 参考文档 官方示例 原理 Cannon.js 使用了欧拉角来表示物体的旋转&#xff0c;…

【小沐学Web3D】three.js 加载三维模型(React)

文章目录 1、简介1.1 three.js1.2 react.js 2、three.js React结语 1、简介 1.1 three.js Three.js 是一款 webGL&#xff08;3D绘图标准&#xff09;引擎&#xff0c;可以运行于所有支持 webGL 的浏览器。Three.js 封装了 webGL 底层的 API &#xff0c;为我们提供了高级的…

简述计算机网络中的七层模型和四层模型

在计算机网络中&#xff0c;网络协议栈的设计通常采用分层结构来处理不同的通信任务。常见的分层结构有OSI七层模型和TCP/IP四层模型。虽然它们的层次数量不同&#xff0c;但本质上都在解决如何有效地进行计算机间通信。本文将分别介绍这两种结构的功能和各层的协议。 一、OSI七…

在 CentOS 上安装 Oracle 数据库

文章目录 **1. 系统准备****1.1 检查系统要求****1.2 更新系统****1.3 安装必要的依赖包****1.4 创建 Oracle 用户和组****1.5 配置内核参数****1.6 配置用户限制****1.7 配置 PAM 模块****1.8 创建 Oracle 安装目录** **2. 下载 Oracle 数据库安装包****2.1 访问 Oracle 官方网…

掌握这些 UI 交互设计原则,提升产品易用性

在当今数字化时代&#xff0c;用户对于产品的体验要求越来越高&#xff0c;UI 交互设计成为决定产品成败的关键因素之一。一个易用的产品能够让用户轻松、高效地完成各种操作&#xff0c;而实现这一目标的核心在于遵循一系列科学合理的 UI 交互设计原则。本文将详细阐述简洁性、…

创新实践分享:基于边缘智能+扣子的智能取物机器人解决方案

在 2024 年全国大学生物联网设计竞赛中&#xff0c;火山引擎作为支持企业&#xff0c;不仅参与了赛道的命题设计&#xff0c;还为参赛队伍提供了相关的硬件和软件支持。以边缘智能和扣子的联合应用为核心&#xff0c;参赛者们在这场竞赛中展现出了卓越的创新性和实用性&#xf…

Python----数据可视化(Pyecharts一:介绍安装,全局配置,系列配置)

一、PyEcharts介绍 1.1、概况 Echarts 是一个由百度开源的数据可视化&#xff0c;凭借着良好的交互性&#xff0c;精巧的图表设计&#xff0c;得到了众多开发者的认可。而 Python 是一门富有表达力的语言&#xff0c;很适合用于数据处理。当数据分析遇上数据可视化时&#xff…

Cursor初体验:excel转成CANoe的vsysvar文件

今天公司大佬先锋们给培训了cursor的使用&#xff0c;还给注册了官方账号&#xff01;跃跃欲试&#xff0c;但是测试任务好重&#xff0c;结合第三方工具开发也是没有头绪。 但巧的是&#xff0c;刚好下午有同事有个需求&#xff0c;想要把一个几千行的excel转成canoe的系统变…

【3DGS】SuperSplat本地运行+修改监听端口+导入ply模型+修剪模型+在线渲染3DGS网站推荐

SuperSplat官网代码&#xff1a;https://github.com/playcanvas/supersplat 本地安装和运行 Clone the repository: git clone https://github.com/playcanvas/supersplat.git cd supersplat Install dependencies: npm install Build SuperSplat and start a local web ser…

MySQL中的B+树索引经验总结

一、什么是B树 B树是一种二叉树&#xff0c;由二叉查找树&#xff0c;平衡二叉树&#xff0c;B树演化而来。 请看上图 B树的特点&#xff1a; 1&#xff09;非叶子节点不存放数据&#xff0c;只存放键值&#xff0c;数据都存放在叶子节点中。 2&#xff09;叶子节点都在同一…

C# NX二次开发:在多个体的模型中如何实现拉伸操作布尔减

大家好&#xff0c;今天接着上一篇拉伸文章去讲。 UF_MODL_create_extruded1 (view source) uf_list_p_tobjectsInputList of objects to be extruded.char *taper_angleInputTaper angle (in degrees).char *limit [ 2 ]InputLimit of extrusion. This is declared as: char …

【深度学习】多源物料融合算法(一):量纲对齐常见方法

目录 一、引言 二、量纲对齐常见方法 2.1 Z-score标准化Sigmoid归一化 2.2 Min-Max 归一化 2.3 Rank Transformation 2.4 Log Transformation 2.5 Robust Scaling 3、总结 一、引言 类似抖音、快手、小红书等产品的信息流推荐业务&#xff0c;主要通过信息流广告、信…

前端高级CSS用法

前端高级CSS用法 在前端开发中&#xff0c;CSS&#xff08;层叠样式表&#xff09;不仅是用来控制网页的外观和布局&#xff0c;更是实现复杂交互和动态效果的关键技术之一。随着前端技术的不断发展&#xff0c;CSS的用法也日益丰富和高级。本文将深入探讨前端高级CSS的用法&a…

How to install a package in offline scenario in Ubuntu 24.04

概述 做过信创项目的兄弟们在工作上每天可能面对很多需要解决的问题&#xff0c;不过&#xff0c;有一类问题可能是大家经常遇的&#xff0c;比方说&#xff0c;有时候我们不得不硬着头皮在离线生产环境中安装某些软件包&#xff0c;相信很多兄弟被这种细碎的小事搞得焦头烂额…

C++类与对象——拷贝构造与运算符重载

拷贝构造函数和赋值运算符重载就是C类默认六个函数之二。 拷贝构造函数&#xff1a; 如果⼀个构造函数的第⼀个参数是自身类类型的引用&#xff0c;且任何额外的参数都有默认值&#xff0c;则此构造函数 也叫做拷贝构造函数&#xff0c;也就是说拷贝构造是⼀个特殊的构造函数…