OpenHarmony Rust开发实战:GN构建配置与FFI互操作指南

news2026/5/16 13:00:51
1. 项目概述为什么要在OpenHarmony里搞Rust最近在折腾OpenHarmony开发板想把一些对性能和安全性要求比较高的模块用Rust重写结果发现官方文档里关于Rust构建的部分讲得比较零散。踩了一圈坑之后我决定把OpenHarmony下Rust模块的配置规则和实操经验系统地梳理出来。如果你也在鸿蒙生态里做底层开发或者想把手头的C/C项目部分功能用Rust安全重构这篇内容应该能帮你省下不少查文档和试错的时间。简单来说OpenHarmony默认的构建系统是GNNinja这是为C/C生态量身打造的编译速度极快。而Rust官方有自己的构建工具Cargo用起来很顺手但和现有的GN构建流水线是两套东西。OpenHarmony的解决方案不是二选一而是做了个“桥接”在GN框架下扩展了对Rust源码.rs文件的直接构建支持。这意味着你可以在同一个BUILD.gn文件里既编译C的动态库也编译Rust的静态库最后把它们链接成一个可执行文件大大提升了混合编程的便利性。核心目标就一个让Rust能无缝融入现有的鸿蒙构建体系同时还能和C/C代码高效、安全地互操作。2. 核心概念与构建框架解析2.1 GN构建系统与Rust的集成逻辑要理解OpenHarmony的Rust支持首先得摸清GNGenerate Ninja是干什么的。你可以把GN看作一个高级的“项目描述语言”生成器。我们写的BUILD.gn文件里面定义了源码路径、依赖关系、编译标志等。GN的作用就是读取这些BUILD.gn文件然后生成一份极其详细、低级的build.ninja文件。这份ninja文件里包含的是一个个具体的编译命令比如clang -c foo.cpp -o foo.o。最后由Ninja这个“超级高效的施工队长”来执行这些命令它只做增量编译依赖关系清晰所以构建速度非常快。那么Rust的Cargo呢Cargo本身也是一个完整的构建系统和包管理器。它管理依赖从crates.io下载、调用rustc编译器、运行测试等。如果完全用Cargo那就和GN体系割裂了。OpenHarmony采用的策略是“GN驱动rustc执行”。具体来说GN作为总指挥你在BUILD.gn中通过特定的Rust模板例如ohos_rust_executable声明一个Rust目标。模板生成rustc命令这些Rust GN模板背后会帮你计算好所有的源码文件、依赖库路径、特性features、编译参数等最终拼接成完整的rustc命令行。Ninja负责执行GN将生成好的rustc命令写入build.ninja由Ninja在构建时调用。对于三方库Cargo crate构建系统会先调用cargo或兼容工具来生成或获取库文件.rlib再将其路径提供给GN进行后续链接。这样做的好处是Rust模块的构建能完全复用OpenHarmony现有的编译框架、配置系统如子系统、部件配置和编译缓存保证了整个项目构建的一致性和高效性。2.2 关键术语与模板全解开始配置前得先搞清楚几个关键术语和所有可用的GN模板这样你在选择时才不会迷糊。Crate这是Rust的编译单元。一个crate可以是一个二进制可执行文件binary crate也可以是一个库library crate。库又分静态库rlib、动态库dylib, cdylib等。在GN体系里一个Rust模块通常对应一个crate。Lint代码检查工具。Rust主要有两类Lintrustc lintsRust编译器自带的检查比如变量未使用、缺失文档注释等。clippy lints更强大的社区工具能发现大量代码风格、复杂性和性能方面的潜在问题。OpenHarmony对这两类Lint都做了分级管理。下表是OpenHarmony提供的所有Rust GN模板这是你配置的基石GN模板功能描述输出文件说明典型使用场景ohos_rust_executable编译Rust可执行文件无后缀的二进制文件 (如my_app)开发独立的Rust应用或测试用例。ohos_rust_shared_library编译Rust动态库 (Rust专用)默认后缀.dylib.so在纯Rust项目内部进行动态链接。ohos_rust_static_library编译Rust静态库 (Rust专用)默认后缀.rlib在纯Rust项目内部进行静态链接这是Rust代码复用的主要方式。ohos_rust_proc_macro编译Rust过程宏库默认后缀.so开发编译时生成或转换代码的宏。ohos_rust_shared_ffi编译FFI动态库 (供C/C调用)默认后缀.so(cdylib)将Rust代码封装成C接口的动态库供上层C/C应用调用。ohos_rust_static_ffi编译FFI静态库 (供C/C调用)默认后缀.a(staticlib)将Rust代码封装成C接口的静态库链接进C/C程序。ohos_rust_cargo_crate集成三方Cargo包可能是.rlib,.dylib.so或二进制引入未预先编译的第三方Rust库源码。ohos_rust_systemtest编译系统测试用例无后缀的二进制文件编写需要系统环境如文件系统、进程的集成测试。ohos_rust_unittest编译单元测试用例无后缀的二进制文件编写针对单个函数或模块的单元测试。ohos_rust_fuzztest编译模糊测试用例无后缀的二进制文件编写用于发现内存安全、逻辑错误的模糊测试。注意这里最容易混淆的是ohos_rust_shared_library和ohos_rust_shared_ffi。前者输出的是dylib主要用于Rust代码之间的动态链接它包含了Rust的元数据metadata其他Rust代码可以用extern crate链接它。后者输出的是cdylib是标准的C风格动态库没有Rust元数据只有C ABI符号专门用于被C/C代码通过dlopen或链接的方式调用。根据你的调用方语言务必选对模板。3. 从零开始配置你的第一个Rust模块理论说再多不如动手试一下。我们从一个最简单的例子开始创建一个Rust静态库rlib然后写一个可执行文件去调用它。这个例子涵盖了最基本的模块定义和依赖关系。3.1 静态库与可执行文件配置实战假设我们的项目目录结构如下my_rust_component/ ├── BUILD.gn └── src/ ├── lib.rs └── main.rs第一步编写Rust库代码 (src/lib.rs)这个文件定义了我们库的公共接口。//! 一个简单的日志打印库。 /// 日志消息结构体 pub struct LogMessage { /// 消息ID pub id: i32, /// 消息内容 pub msg: String, } /// 打印日志消息到标准输出 pub fn print_log(msg: LogMessage) { // 这里使用println!在实际OpenHarmony设备上可能需要适配hilog println!([LIB] ID: {}, Message: {}, msg.id, msg.msg); }第二步编写可执行文件代码 (src/main.rs)这个文件是程序的入口它会调用我们上面写的库。//! 主程序演示调用静态库。 // 声明外部cratemy_logger是在BUILD.gn中定义的crate_name extern crate my_logger; use my_logger::{LogMessage, print_log}; fn main() { let msg LogMessage { id: 1001, msg: Hello from Rust executable!.to_string(), }; print_log(msg); println!([MAIN] Program finished.); }第三步编写核心的BUILD.gn文件这个文件告诉GN如何构建我们的库和可执行文件。import(//build/ohos.gni) # 导入OpenHarmony基础GN配置 # 1. 首先定义静态库 (rlib) ohos_rust_static_library(my_logger_rlib) { # 指定库的源码文件 sources [ src/lib.rs, ] # **重要**指定crate的名称这个名称会在Rust代码的extern crate中使用 crate_name my_logger # 指定crate类型为rlib静态库 crate_type rlib # 启用标准库支持在OpenHarmony用户态开发中通常需要 features [ std ] # 可以在这里配置Lint等级例如使用vendor级检查 # rustc_lints vendor # clippy_lints vendor } # 2. 然后定义可执行文件它依赖于上面的静态库 ohos_rust_executable(my_rust_app) { # 指定可执行文件的源码 sources [ src/main.rs, ] # 声明依赖格式为 :目标名 deps [ :my_logger_rlib, ] # 可执行文件不需要crate_name和crate_type模板会处理 }第四步编译与运行在你的OpenHarmony项目根目录下执行编译命令指定你的部件或模块路径。例如如果你的模块放在applications/sample/my_rust_component下./build.sh --product-name rk3568 --build-target applications/sample/my_rust_component:my_rust_app实操心得--build-target后面的参数格式是路径:目标名。目标名就是你在BUILD.gn里定义的ohos_rust_executable的名字这里是my_rust_app。直接指定这个可执行目标会连带它的所有依赖如my_logger_rlib一起编译。编译成功后在输出目录例如out/rk3568/packages/phone/bin找到my_rust_app文件推送到开发板并运行# 在开发板上 ./my_rust_app预期输出[LIB] ID: 1001, Message: Hello from Rust executable! [MAIN] Program finished.这个流程是OpenHarmony Rust开发最基础的范式先定义库再定义依赖该库的可执行文件。deps字段是GN中模块间依赖关系的关键。3.2 集成第三方Cargo库详解实际项目中我们几乎一定会用到第三方库。OpenHarmony提供了ohos_rust_cargo_crate模板来处理这种情况。它最大的特点是能处理带有build.rs构建脚本的crate这是很多Rust三方库用来进行条件编译、代码生成的标准方式。假设我们需要集成一个虚构的、带有build.rs的第三方库network_helper。项目结构my_network_app/ ├── BUILD.gn └── vendor/ └── network_helper/ # 这是我们从crates.io下载或拷贝的三方库源码 ├── Cargo.toml ├── build.rs └── src/ └── lib.rsBUILD.gn配置示例import(//build/templates/rust/ohos_cargo_crate.gni) # 注意导入的模板不同 # 定义三方库目标 ohos_rust_cargo_crate(network_helper_crate) { # 三方库的名称通常与Cargo.toml中的[package] name一致 crate_name network_helper # 库的根文件路径 crate_root vendor/network_helper/src/lib.rs # 需要参与编译的所有源码文件 sources [ vendor/network_helper/src/lib.rs, vendor/network_helper/src/*.rs, # 可以使用通配符 ] # **关键**指定build.rs脚本的路径 build_root vendor/network_helper/build.rs build_sources [ vendor/network_helper/build.rs ] # **关键**声明build.rs脚本会生成哪些文件GN会据此建立依赖 build_script_outputs [ generated_config.rs ] # 启用该crate的某些特性 features [ std, async-std-runtime ] # 传递给rustc的编译标志 rustflags [ --cfg, unix ] # 设置构建时环境变量build.rs可以通过std::env::var读取 rustenv [ TARGET_OSohos, CUSTOM_NUMBER42, ] } # 你的主应用依赖这个三方库 ohos_rust_executable(my_network_app) { sources [ src/main.rs ] deps [ :network_helper_crate, # 依赖刚才定义的三方库目标 ] }build.rs是如何工作的构建系统在编译network_helper_crate之前会先编译并运行它的build.rs脚本。这个脚本可以探测编译环境如Rust版本、目标平台。根据环境变量上面rustenv设置的生成不同的代码。将生成的代码写入$OUT_DIR目录由构建系统指定。通过println!(cargo:rustc-cfghas_feature_x);这样的指令告诉rustc启用特定的条件编译配置。ohos_rust_cargo_crate模板的核心作用就是模拟了Cargo在构建三方库时的环境和工作流程确保那些依赖build.rs的复杂crate能在GN体系下正确编译。注意事项对于没有build.rs的简单三方库理论上你可以直接用ohos_rust_static_library并把所有源码放进sources。但使用ohos_rust_cargo_crate是更标准、兼容性更好的做法因为它能正确处理Cargo的特性解析和依赖传递如果该crate还依赖其他crate。对于复杂的、来自crates.io的库建议使用OpenHarmony提供的cargo2gn工具自动生成BUILD.gn片段这比手动配置要可靠得多。4. 进阶配置FFI互操作与Lint规范当你的Rust模块需要和OpenHarmony主体大量C/C代码对话时FFIForeign Function Interface就是桥梁。同时为了保证代码质量必须理解OpenHarmony的Lint规范。4.1 Rust与C/C的互操作FFIFFI的核心是创建C ABI兼容的接口。OpenHarmony提供了专门的模板来简化这个过程。场景一Rust调用C/C库例如调用libhilog打印日志假设OpenHarmony的SDK提供了libhilog.so库用于日志输出。确保C库输出正确后缀默认情况下OpenHarmony编译的动态库后缀是.z.so如libhilog.z.so。但Rust的#[link]属性默认寻找.so。因此在C/C动态库的BUILD.gn中需要添加ohos_shared_library(hilog) { # ... 其他配置 output_extension so # 强制输出为 .so 而非 .z.so }这一步通常由SDK或底层库的开发者完成应用开发者需要确认你依赖的库是否已经这样配置。在Rust中声明和调用// src/ffi_demo.rs // 使用 extern C 块声明外部C函数 #[link(name hilog)] // 注意这里写hilog不是libhilog extern C { // 假设hilog的C函数原型是int OH_LogPrint(LogLevel level, const char* tag, const char* fmt, ...); fn OH_LogPrint(level: i32, tag: *const std::os::raw::c_char, fmt: *const std::os::raw::c_char, ...) - i32; } pub fn log_to_hilog(level: i32, tag: str, message: str) { use std::ffi::CString; let c_tag CString::new(tag).unwrap(); let c_msg CString::new(message).unwrap(); unsafe { // 调用不安全的外部函数 OH_LogPrint(level, c_tag.as_ptr(), c_msg.as_ptr()); } }对应的BUILD.gn需要让Rust模块依赖这个C库ohos_rust_static_library(my_rust_ffi_lib) { sources [ src/ffi_demo.rs ] crate_name ffi_demo # 声明外部依赖//base/hiviewdfx/hilog是hilog模块的GN路径 external_deps [ hilog:hilog ] // 格式通常为 部件名:模块名 }场景二C/C调用Rust库更常见你需要将Rust代码编译成C风格的动态库cdylib或静态库staticlib。编写Rust FFI接口// src/lib.rs use std::ffi::{CStr, CString}; use std::os::raw::c_char; // 标记为 #[no_mangle] 防止函数名被编译器混淆 // 使用 extern C 指定C ABI #[no_mangle] pub extern C fn rust_generate_greeting(name: *const c_char) - *mut c_char { // 将C字符串转换为Rust字符串不安全操作 let c_str unsafe { CStr::from_ptr(name) }; let name_str match c_str.to_str() { Ok(s) s, Err(_) Invalid UTF-8, }; // 生成问候语 let greeting format!(Hello, {} from Rust!, name_str); // 将Rust字符串转换为C字符串并移交所有权调用者需负责释放 CString::new(greeting).unwrap().into_raw() } // 提供一个释放字符串的函数 #[no_mangle] pub extern C fn rust_free_string(s: *mut c_char) { unsafe { if s.is_null() { return; } // 将指针转换回CString并丢弃内存即被释放 let _ CString::from_raw(s); } }使用ohos_rust_shared_ffi模板编译ohos_rust_shared_ffi(my_rust_ffi) { sources [ src/lib.rs ] crate_name my_ffi crate_type cdylib # 编译为C动态库 # 可能需要定义一些特性来控制代码生成 features [ std ] }编译后会生成libmy_rust_ffi.so。C/C代码就可以像调用普通动态库一样使用dlopendlsym或直接链接来调用rust_generate_greeting和rust_free_string函数了。避坑指南FFI中最头疼的是内存管理。Rust和C/C对内存的所有权和生命周期管理方式截然不同。上面的例子展示了经典模式Rust返回一个由CString::into_raw()获得的原始指针表示所有权已转移给调用者。调用者C端必须在使用后调用Rust提供的rust_free_string来释放内存否则会导致内存泄漏。务必为每一个into_raw()配对一个释放函数并在文档中明确约定。4.2 Lint规则配置与代码规范OpenHarmony对代码质量有严格要求通过Lint规则来强制执行。Rust模块的Lint分为rustc_lints编译器检查和clippy_lints代码风格检查两类每类又分三个等级。Lint等级详解openharmony最严格等级。适用于OpenHarmony核心框架和应用层代码。会开启大量警告warnings甚至将一些风格问题视为错误errors例如强制要求公共项必须有文档注释 (-D missing-docs)。vendor中等严格等级。适用于厂商vendor定制代码。会放宽一些风格要求但基本的正确性和安全性检查仍然保留。none关闭所有强制性Lint检查。仅适用于第三方代码third_party或预编译件prebuilts因为这些代码可能不符合OpenHarmony规范修改成本高。如何配置 你可以在BUILD.gn中为每个Rust目标显式设置Lint等级ohos_rust_executable(my_strict_app) { sources [ src/main.rs ] rustc_lints openharmony # 启用最严格的rustc检查 clippy_lints vendor # 启用中等严格的clippy检查 }路径自动匹配规则 如果你不显式配置rustc_lints或clippy_lints构建系统会根据模块源码所在的路径自动判断等级规则如下源码所在路径前缀自动应用的Lint等级third_party/noneprebuilts/nonevendor/vendordevice/vendor其他所有路径openharmony实操心得在项目初期尤其是调试FFI或不熟悉的第三方库时可以暂时在模块中设置rustc_lints none和clippy_lints none来绕过Lint错误快速验证功能。但功能稳定后强烈建议将等级至少提升到vendor并逐步解决所有警告。将警告视为错误来处理是写出健壮Rust代码的好习惯。对于团队项目应在CI/CD流水线中强制执行openharmony等级的Lint检查。5. 常见问题排查与调试技巧在实际开发中你肯定会遇到各种构建和运行问题。这里记录了几个最常见的问题和我的解决思路。5.1 编译期问题速查表问题现象可能原因排查步骤与解决方案error: linking with aarch64-ohos-clang failed链接器错误通常是找不到C/C库的符号。1. 检查external_deps或deps是否正确声明了C/C库的GN目标。2. 确认被依赖的C库在它的GN中设置了output_extension so。3. 使用./build.sh --build-target your_target --verbose查看详细的链接命令确认-L和-l参数是否正确。error[E0463]: cant find crate for xxxRust编译器找不到依赖的crate。1. 检查deps中依赖的Rust目标名是否拼写正确前面是否有冒号如:my_logger_rlib。2. 确认被依赖的库如ohos_rust_static_library的crate_name属性是否与源码中extern crate的名字一致。3. 确保依赖的库和当前模块在同一个产品配置中都被编译。build.rs脚本中的环境变量读取为None构建脚本未收到预期的环境变量。1. 确认在ohos_rust_cargo_crate的rustenv数组中正确设置了环境变量。2. 环境变量名在build.rs中通过std::env::var(VAR_NAME)读取检查拼写。3. 构建脚本的输出println!通常在编译日志中查看日志确认build.rs是否被执行以及打印的信息。warning: unused import, 但代码确实需要Lint检查过于严格。1. 这是Lint警告不是错误。如果确认导入是必要的例如用于 trait 实现可以在导入前加#[allow(unused_imports)]局部禁用警告。2. 或者考虑调整模块的rustc_lints等级例如从openharmony降到vendor但这不是首选方案。编译速度慢尤其是三方库ohos_rust_cargo_crate每次都可能从头编译。1. OpenHarmony的构建缓存对GN目标有效。确保你的BUILD.gn配置稳定避免sources列表使用过于宽泛的通配符导致缓存失效。2. 对于极少变动的三方库可以考虑将其预编译为.rlib文件然后通过ohos_prebuilt_rust_library如果存在或直接指定路径的方式引入避免每次编译。5.2 运行时与调试技巧如何查看详细的构建命令在编译时添加--verbose或-v参数。这是最强大的调试手段它能展示GN生成的每一个Ninja命令包括具体的rustc调用参数、链接器参数等。通过对比命令可以精准定位路径错误、参数缺失等问题。./build.sh --product-name rk3568 --build-target my_app --verboseRust的println!在OpenHarmony设备上不输出在OpenHarmony的用户态环境中标准输出stdout可能没有被重定向到控制台。生产代码中应该使用OpenHarmony的HiLog日志系统。参考上面的FFI示例通过FFI调用libhilog.so中的日志函数。在开发调试阶段可以临时链接一个简单的、将日志写入文件的C库或者使用adb shell连接到设备后通过hdc shell运行程序并观察系统日志hilog。如何对Rust代码进行交叉编译和调试交叉编译OpenHarmony的GN构建系统已经帮你处理好了。你只需要在顶层通过--product-name指定目标产品如rk3568构建系统会自动选择对应的工具链包括rustc的目标三元组如aarch64-unknown-linux-ohos。调试你需要使用支持该目标架构的调试器如gdb或lldb的对应版本。将编译生成的带调试符号的可执行文件推送到设备在设备上启动调试服务gdbserver然后在主机上用交叉编译版本的gdb进行远程连接和调试。这个过程比较繁琐建议在复杂问题排查时才使用。对于逻辑问题多依赖Rust强大的编译期检查和编写充分的单元测试。单元测试和系统测试怎么跑使用ohos_rust_unittest和ohos_rust_systemtest模板编译出的测试用例本身就是一个可执行文件。编译完成后将其推送到设备上直接运行即可。测试框架如libtest的输出会通过标准输出显示。你可以将测试用例的构建目标加入到产品的测试套件中利用OpenHarmony的测试框架统一调度和执行。最后我个人在OpenHarmony上实践Rust开发最大的体会是耐心阅读构建错误信息。Rust编译器的错误信息在所有语言中算是非常友好和详细的它会明确指出类型不匹配、所有权问题、生命周期错误等。而GN/Ninja的错误信息则更偏向于“文件找不到”、“命令执行失败”。遇到问题先从终端输出的第一行错误开始看逐层向上分析。混合编程时明确区分问题是出在Rust编译阶段、C/C编译阶段还是最后的链接阶段能极大缩小排查范围。把OpenHarmony的构建系统看作一个精密的流水线理解每个模板在流水线中的角色配置起来就会得心应手。

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

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

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…