鸿蒙NDK实战:如何高效集成第三方SO库

鸿蒙使用第三方SO库 1、将MNN和Opencv的so文件(包括.407文件),放入模块下libs目录对应的版本(arm64-v8a和armeabi-v7a)补充说明:放置so文件时,注意对应的407也需要一同放入(由于windows环境的特殊)使用第三方SO库以导入OpenCV和MNN的SO库为例。 阅读详情

1. 为什么鸿蒙应用需要“特别定制”的SO库?

如果你是从Android开发转战鸿蒙,或者之前玩过Linux下的C++开发,第一次在鸿蒙项目里集成一个现成的.so文件时,大概率会碰一鼻子灰。明明文件放对了地方,编译也没报错,但一运行就给你来个“模块未定义”或者直接闪退。这事儿我刚开始也栽过跟头,折腾了半天才发现,问题的核心在于鸿蒙的Napi(Node-API) 规范。

简单来说,鸿蒙应用(特别是基于ArkTS/ArkUI开发的应用)的运行环境,和传统的Linux或Android有本质区别。你的JavaScript/ArkTS代码跑在一个叫“方舟运行时”的环境里,而你的C/C++原生代码(编译成SO库)跑在另一个“原生层”。这两个世界要想安全、高效地对话,必须遵守一套严格的“外交协议”——这就是Napi。它定义了两边如何交换数据(比如把ArkTS的字符串传给C++函数)、如何管理内存(防止一边还在用,另一边却给释放了)、以及如何抛出和捕获异常。

所以,一个在Linux下用GCC或者Android下用NDK常规编译出来的SO库,是听不懂鸿蒙Napi的“语言”的。直接把它丢进鸿蒙项目,就像让一个只懂英语的人去参加中文会议,根本无法沟通。鸿蒙系统根本不会去调用它里面的函数,因为它不符合Napi的调用约定和生命周期管理规则。这就是为什么官方文档和很多文章都强调:鸿蒙应用必须使用基于Napi编译的SO库。

那么,我们手头已有的那些功能强大、历经考验的第三方C/C++库(比如图像处理的OpenCV、音频编码的FFmpeg、各种加密算法库)就没用了吗?当然不是!我们的核心任务,就是为这些“外国友人”配备一个“Napi翻译官”,让它们能顺利融入鸿蒙的生态。这个过程,就是“封装”或“桥接”。理解了这一点,后续的所有步骤——是用鸿蒙NDK重编,还是做一层Napi封装——就都有了清晰的指导思想。

2. 实战准备:认识鸿蒙NDK与工程结构

工欲善其事,必先利其器。在开始动手封装或编译之前,我们得先把家伙事儿和场地搞清楚。鸿蒙的NDK(Native Development Kit) 就是我们的核心工具包,它基于Clang/LLVM工具链,并深度集成了对Napi的头文件和支持库。你需要从HarmonyOS应用开发的官方渠道获取并配置好它。

我建议在你的开发机上,为鸿蒙NDK设置一个独立的环境变量,比如HARMONYOS_NDK_HOME,指向它的根目录。这样在后续的编译脚本里引用起来会非常方便,也避免了和Android NDK搞混。你可以打开终端,输入$HARMONYOS_NDK_HOME/toolchains/llvm/prebuilt/{host}/bin/clang++ --version来验证一下是否配置正确。

接下来,我们看看一个标准的、需要集成原生代码的鸿蒙应用工程应该长什么样。光把SO文件扔进libs文件夹是远远不够的,需要一个更清晰的结构来管理你的C/C++代码、头文件和构建脚本。下面是我在多个项目中总结出来的一种推荐结构:

MyHarmonyApp/
├── entry/ # 主模块
│   ├── src/
│   │   ├── main/
│   │   │   ├── cpp/          # 存放你的C/C++源码和Napi封装层代码
│   │   │   │   ├── CMakeLists.txt    # 最重要的构建脚本
│   │   │   │   ├── my_napi_bridge.cpp # 你写的Napi封装函数
│   │   │   │   └── third_party/      # 放置第三方库的源码或头文件
│   │   │   │       ├── include/
│   │   │   │       └── src/
│   │   │   ├── resources/
│   │   │   └── ets/          # 你的ArkTS业务代码
│   │   │       └── pages/
│   │   └── ohosTest/
│   └── libs/                 # 最终存放编译好的、符合Napi规范的SO文件
│       ├── arm64-v8a/
│       └── armeabi-v7a/
├── oh-package.json5          # 模块依赖声明文件
└── build-profile.json5       # 项目构建配置

这个结构的关键在于cpp目录和它里面的CMakeLists.txt。鸿蒙的构建系统Hvigor(现在逐渐转向Ohos Build)在编译应用时,会识别这个目录,并调用CMake来编译其中的原生代码,最终生成符合要求的SO库,自动打包到HAP里。libs文件夹在这里的角色更倾向于存放“预编译好的、符合Napi规范的依赖库”,或者作为最终产物的输出目录。而需要你动手编写和干预的,正是cpp目录下的内容。

3. 方案一:使用鸿蒙NDK直接编译第三方源码

这是最“原生”、最推荐的方式,前提是你能拿到第三方库的C/C++源代码。它的好处是集成度最高,编译出的SO库天然符合Napi环境,性能损耗最小,也便于后续调试。我以集成一个虚构的、但非常经典的libawesome.a静态库(或它的源码)为例,带你走通全流程。

假设libawesome提供了一个计算斐波那契数列的函数int awesome_fibonacci(int n)。我们的目标是让ArkTS能调用它。

第一步:安置源码与头文件。 将awesome.h头文件放到cpp/third_party/include/下,将awesome.c源码(或者.a静态库文件)放到cpp/third_party/src/下。如果是一个庞大的开源库,你可能需要把整个源码目录拷贝过来。

第二步:编写Napi桥接层。 这是核心步骤。我们在cpp/my_napi_bridge.cpp中创建一个Napi函数,作为ArkTS和libawesome之间的桥梁。

#include "napi/native_api.h" // 鸿蒙NDK提供的核心头文件
#include "third_party/include/awesome.h" // 引入第三方库头文件

// 这个函数将是暴露给ArkTS的接口
static napi_value JsFibonacci(napi_env env, napi_callback_info info) {
    // 1. 获取ArkTS传递过来的参数个数和值
    size_t argc = 1;
    napi_value args[1];
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 2. 参数校验与类型转换:将Napi的value转换为C的int
    int n;
    napi_get_value_int32(env, args[0], &n);

    // 3. 调用真正的第三方库函数!
    int result = awesome_fibonacci(n);

    // 4. 将C函数的结果转换回Napi的value,返回给ArkTS
    napi_value jsResult;
    napi_create_int32(env, result, &jsResult);
    return jsResult;
}

// 模块初始化函数,必须要有。它向鸿蒙运行时注册我们提供的接口。
static napi_value Init(napi_env env, napi_value exports) {
    // 定义一个属性描述符,告诉系统JsFibonacci函数的元信息
    napi_property_descriptor desc = {
        "fibonacci", // ArkTS中调用的函数名
        nullptr,
        JsFibonacci, // 对应的C函数指针
        nullptr,
        nullptr,
        nullptr,
        napi_default,
        nullptr
    };
    // 将函数注册到exports对象上
    napi_define_properties(env, exports, 1, &desc);
    return exports;
}

// 模块声明,宏定义。注意模块名“awesome”要和后续配置对应。
NAPI_MODULE(awesome, Init)

第三步:配置CMakeLists.txt,指挥编译。 这个文件告诉CMake如何编译你的代码,并链接第三方库。

# CMake最低版本要求
cmake_minimum_required(VERSION 3.4.1)
# 项目名
project(MyNativeModule)

# 设置编译目标为SHARED库(即.so文件),库名定为“awesome”
add_library(awesome SHARED
    ./my_napi_bridge.cpp # 你的桥接文件
    # 如果第三方库是源码,在这里添加它的源文件,例如:
    # ./third_party/src/awesome.c
)

# 指定头文件搜索路径,这样#include才能找到文件
target_include_directories(awesome PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}/third_party/include
)

# 关键!链接鸿蒙的Napi库。没有这个,你的函数注册不了。
target_link_libraries(awesome PUBLIC libace_napi.z.so)

# 如果第三方库是预编译的静态库(.a),在这里链接它
# target_link_libraries(awesome PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/third_party/lib/libawesome.a)

# 设置编译属性,非常重要!
set_target_properties(awesome PROPERTIES
    CXX_STANDARD 11 # C++标准
    CXX_STANDARD_REQUIRED ON
    # 指定生成的SO库的文件名前缀,鸿蒙约定为“lib”
    LIBRARY_OUTPUT_NAME "libawesome"
    # 输出目录,可以指定到项目的libs下对应ABI子目录
    # LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../libs/${OHOS_ARCH}/
)

第四步:在oh-package.json5中声明原生模块。 告诉鸿蒙的打包工具,我们这个模块依赖一个叫awesome的原生库。

{
  "license": "...",
  "devDependencies": { ... },
  "dependencies": {
    // 其他ArkTS库依赖...
  },
  "nativeLibs": {
    // 声明原生库依赖,name必须和CMake中add_library的库名一致
    "awesome": {
      "path": "./src/main/cpp" // 指向CMakeLists.txt所在目录
    }
  }
}

完成以上四步,编译整个项目。如果一切顺利,构建系统会自动在cpp目录下执行CMake,编译出libawesome.so,并打包进HAP。你可以在build目录的输出产物里找到它。

4. 方案二:为现有SO库封装Napi层

很多时候,我们拿不到第三方库的源码,只有一个编译好的libthird.so文件。或者这个库依赖复杂,用鸿蒙NDK从头编译困难重重。这时,我们就需要**“封装层(Wrapper)”** 方案。

这个方案的思路是:我们不重新编译libthird.so,而是用鸿蒙NDK新建一个符合Napi规范的SO库(比如叫libwrapper.so)。在这个新库里,我们编写Napi函数,然后在Napi函数内部,通过动态链接的方式,去调用libthird.so里的原始函数。libwrapper.so是鸿蒙应用的“合法公民”,它负责和ArkTS打交道,并私下里和“外来”的libthird.so沟通。

操作步骤:

  1. 放置原始SO库:将libthird.so放入entry/src/main/libs/[对应的ABI,如arm64-v8a]/目录下。鸿蒙的打包系统会自动将这个目录下的SO库打包到HAP的libs目录中。
  2. 创建封装层代码:和方案一类似,在cpp目录下创建wrapper.cpp。但代码有所不同:
#include "napi/native_api.h"
#include <dlfcn.h> // 用于动态加载SO库

// 定义原始函数指针类型
typedef int (*orig_func_t)(int);

static napi_value JsCallThirdLib(napi_env env, napi_callback_info info) {
    // 1. 动态打开已打包在应用内的原始SO库
    // 注意:库名不需要“lib”前缀和“.so”后缀,系统会自动查找。
    void* handle = dlopen("libthird.so", RTLD_LAZY);
    if (!handle) {
        // 处理错误,dlopen失败
        napi_throw_error(env, nullptr, dlerror());
        return nullptr;
    }

    // 2. 根据符号名(函数名)获取函数地址
    orig_func_t orig_func = (orig_func_t)dlsym(handle, "original_function_name");
    if (!orig_func) {
        dlclose(handle);
        napi_throw_error(env, nullptr, dlerror());
        return nullptr;
    }

    // 3. 获取ArkTS参数
    size_t argc = 1;
    napi_value args[1];
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    int input;
    napi_get_value_int32(env, args[0], &input);

    // 4. 调用原始SO库中的函数!
    int result = orig_func(input);

    // 5. 关闭句柄(根据情况,也可在模块生命周期内保持打开)
    dlclose(handle);

    // 6. 返回结果给ArkTS
    napi_value jsResult;
    napi_create_int32(env, result, &jsResult);
    return jsResult;
}

// 同样的模块初始化...
static napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc = {"callThirdLib", nullptr, JsCallThirdLib, nullptr, nullptr, nullptr, napi_default, nullptr};
    napi_define_properties(env, exports, 1, &desc);
    return exports;
}

NAPI_MODULE(wrapper, Init)
  1. 配置CMakeLists.txt:这个CMake文件只编译wrapper.cpp,生成libwrapper.so。它不需要链接libthird.so,因为我们是运行时动态加载。但需要链接libdl(提供dlopen等函数)。
cmake_minimum_required(VERSION 3.4.1)
project(WrapperModule)

add_library(wrapper SHARED ./wrapper.cpp)
target_include_directories(wrapper PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(wrapper PUBLIC libace_napi.z.so libdl.z.so) # 链接dl库
set_target_properties(wrapper PROPERTIES
    LIBRARY_OUTPUT_NAME "libwrapper"
)
  1. 修改oh-package.json5:声明我们新创建的封装库。
{
  ...
  "nativeLibs": {
    "wrapper": {
      "path": "./src/main/cpp"
    }
  }
}

这个方案的优缺点非常明显:

  • 优点:无需第三方库源码,集成速度快。对于闭源库或编译极其复杂的库是唯一选择。
  • 缺点:引入了一层间接调用,有微小的性能开销。更重要的是,ABI兼容性是个大坑。原始libthird.so必须是用与鸿蒙NDK兼容的工具链(如相同的Clang版本、C++标准库)为相同的CPU架构(armeabi-v7a, arm64-v8a)编译的。否则,dlopen或dlsym可能会失败,或者运行时出现难以预料的崩溃。我强烈建议在集成前,用readelf -d libthird.so | grep NEEDED和objdump -T libthird.so等命令检查一下它的动态依赖和符号表,确保没有不兼容的依赖(比如GNU的libstdc++,而鸿蒙通常使用LLVM的libc++)。

5. 避坑指南与效能优化

踩过坑才知道路平。下面是我在实际项目中总结的几个关键问题和解决方案。

坑一:NDK版本与API Target不匹配。 鸿蒙NDK的版本需要和你的DevEco Studio以及目标设备的HarmonyOS API版本对应。用旧版NDK编译的库,可能无法在搭载新系统的设备上运行。我的习惯是,在项目的build-profile.json5或CMakeLists.txt开头就明确指定API级别和NDK路径,确保团队统一。

坑二:CMake编译参数调优。 直接使用默认的CMake配置有时会生成体积较大或性能未优化的库。我通常会添加这些配置:

# 在add_library之后,设置目标属性
set_target_properties(my_lib PROPERTIES
    # 启用编译优化(发布版)
    CMAKE_CXX_FLAGS_RELEASE "-O2 -flto"
    # 隐藏不必要的符号,减小库体积
    C_VISIBILITY_PRESET hidden
    CXX_VISIBILITY_PRESET hidden
    VISIBILITY_INLINES_HIDDEN ON
)
# 显式链接必要的系统库,避免运行时找不到
target_link_libraries(my_lib PUBLIC
    libace_napi.z.so
    libc++.so # 使用LLVM的C++标准库
    # libz.so # 如果需要压缩功能
)

坑三:多线程安全与内存管理。 Napi环境是支持多线程的。如果你的原生函数会被多个ArkTS Worker同时调用,务必确保它是线程安全的,或者使用napi_create_threadsafe_function进行安全回调。内存管理是另一个重灾区,牢记“谁申请,谁释放”的原则。从Napi env中创建的任何对象(如napi_create_string_utf8),其生命周期通常由JavaScript的垃圾回收机制管理,但你通过malloc或new在C++侧分配的内存,必须自行free或delete,避免内存泄漏。

坑四:调试与日志输出。 原生代码调试不如ArkTS方便,打好日志是关键。除了使用标准的printf或std::cout(输出到logcat),鸿蒙NDK也提供了hilog日志系统,功能更强大,可以按级别过滤。

#include "hilog/log.h"
#undef LOG_DOMAIN
#undef LOG_TAG
#define LOG_DOMAIN 0xXXXX // 你的领域ID
#define LOG_TAG "MyNativeModule"

// 在函数中使用
OH_LOG_DEBUG(LOG_APP, "JsFibonacci called with n=%{public}d", n);

在DevEco Studio的Log窗口,选择对应的进程和设备,就能看到这些日志,对于追踪复杂逻辑的流程和定位崩溃点至关重要。

最后,关于效能,对于性能敏感的模块,我建议在封装层尽量减少数据拷贝和格式转换的次数。比如,如果ArkTS需要传递一个大数组给C++处理,可以考虑使用napi_get_arraybuffer_info直接获取底层ArrayBuffer的指针进行操作,而不是将每个元素逐个转换。这能极大提升数据交换的效率。集成第三方SO库,尤其是封装方案,第一次成功运行的那一刻会很有成就感。但真正的挑战往往在于后续的维护、性能优化和跨版本兼容。保持你的CMake脚本清晰,为不同的ABI做好构建配置,并在关键函数加上足够的日志,这些好习惯能让未来的你感谢现在的自己。

OpenHarmony NDK实战:三方so库鸿蒙化编译与集成指南 本文详细介绍了在OpenHarmony系统中进行NDK开发时,如何将第三方so库进行鸿蒙化编译与集成的完整流程。从环境准备、工具链配置、CMake升级到实战编译FFmpeg等库,提供了详尽的操作步骤和常见问题解决方案,帮助开发者高效完成鸿蒙生态下的原生库迁移与集成工作。 阅读详情

相关推荐

【鸿蒙实战开发】—— NDK构建工程

HarmonyOS NDK默认使用CMake作为构建系统,随包提供了符合HarmonyOS工具链的基础配置文件 ohos.toolchain.cmake,用于预定义CMake变量来简化开发者配置。从源码构建源码构建也有不同方式:* 可以使用DevEco Studio提供的C++应用模板,用DevEco Studio来编译构建* 也可以使用命令行CMake来编译构建使用预构建库构建本章节将通过具体示例介绍如何在Native工程中使用NDK,以及如何编写CMake脚本来构建NDK工程。

2401_88547687的博客 1273

鸿蒙ArkTs加载各种so动态链接库教程,包括适用于鸿蒙的动态库和通用linux动态链接库,堕胎级教程,一篇就够了,玩转so加载

本文包含鸿蒙ArkTs加载os专用的so库与so库两部分如果你手上有c源代码参考笔者这篇文章如果你手上的so库是适用于ArkTs的(类似于Node的 C/C++ addons with N-API),直

qq_17432441的博客 8134

HarmonyOS Next鸿蒙NDK使用示例

HarmonyOS Next鸿蒙NDK使用指南

JohnLiu的博客 1925

编译一份适用于鸿蒙ArkTs的so动态库教学,提供给第三方导入并使用

鸿蒙 harmonyos c语言编译成so动态链接库,并提供给第三方使用。 ArkTs导入第三方so库并使用教程

qq_17432441的博客 9130

鸿蒙开发实战:如何快速集成第三方SO库(NDK+napi版)

本文详细介绍了在鸿蒙应用开发中,如何利用NDK和Node-API(napi)高效、安全地集成第三方SO库。文章从环境准备、项目结构搭建讲起,深入解析了NDK与napi的核心作用,并通过一个完整的图像处理库集成实战案例,手把手演示了封装层开发、CMake配置、模块声明及ArkTS调用的全流程,最后提供了关键的疑难排查与性能优化指南,帮助开发者规避常见陷阱,充分发挥原生代码的性能优势。

weixin_29267307的博客 294

鸿蒙HarmonyOS应用开发之在NDK工程中使用预构建库

在NDK工程中,可以通过CMake语法规则引入并使用预构建库。在引用预构建库时,模块libs目录中的预构建库,以及在CMakeList.txt编译脚本中声明的预构建库都会被打包。例如在项目中需要使用预构建库libavcodec_ffmpeg.so,其开发态存放路径如下图所示。当在HAR中使用预构建库时,当前编译的库和链接所需预构建库会打包到HAR中的libs目录下,如下图所示。为了解决大家这些学习烦恼。

YHDMYBY的博客 1049

so加载 - Linker跟NameSpace知识 (上篇)

so库的加载可是我们日常开发都会用到的,因此系统也提供了非常方便的api给我们进行调用```System.loadLibrary(xxxso);``` 当然,随着版本的变化,loadLibrary也是出现了非常大的变化,最重要的是分水岭是androidN加入了**namespace**机制,可能很多人都是一头雾水噢!这是个啥?我们在动态so加载方案中,会频繁出现这个名词,同时还有一个高频的词就是**Linker**,本期不涉及复杂的技术方案,我们就来深入聊聊,Linker的概念,与namespac

大模型训练 1344

鸿蒙HarmonyOS应用开发之NDK工程构建

ohos.toolchain.cmake是OpenHarmony NDK提供给CMake的toolchain脚本,里面预定义了编译OpenHarmony应用需要设置的编译参数,如交叉编译设备的目标、C++运行时库的链接方式等;这些参数在调用CMake命令时,可以从命令行传入,来改变默认编译链接行为。此文件中的常用参数见下表。参数类型说明OHOS_STLlibc++的链接方式。默认为c++_shared。c++_shared表示采用动态链接libc++_shared.so;

YHDMYBY的博客 1419

鸿蒙5.0开发【HSP/HAR包中如何引用外部编译的so库文件】应用运维

libxxx.so库文件放入HAR或HSP的libs/arm64-v8a目录。设备类型不同时,需添加对应子目录。新版的arm64为libs/arm64-v8a,老版的arm64为libs/armeabi-v7a,x86模拟器为libs/x86_64。在src/main/cpp/CMakeLists.txt文件中链接so库文件。

鸿蒙的技术博客 521

避坑指南:鸿蒙调用非Napi版SO库的3种解决方案

本文针对鸿蒙应用开发中调用非Napi版SO库的常见难题,提供了三种核心解决方案:构建Napi封装层、利用接口转换工具以及源代码重编译。文章详细分析了每种方案的适用场景、实施步骤与优劣,并提供了决策指南,帮助开发者根据项目实际情况选择最有效的技术路径,实现第三方原生库的顺利迁移与集成。

weixin_29250573的博客 404

从桨叶设计到电机匹配:手把手教你调出无人机最佳动力组合

本文系统介绍了无人机动力系统的核心匹配原则,重点解析了如何通过测试与数据分析,优化螺旋桨与电机的组合,从而显著提升系统力效与续航。文章提供了从参数解读、实战测试到深度调优的完整指南,帮助开发者解决电机过热、推力不足等常见问题,实现无人机性能最大化。

weixin_29305313的博客 235

鸿蒙NEXT版实战开发:在Native侧如何集成三方SO库?

在Native侧如何集成三方SO库.....

qq_39652397的博客 545

Matlab激活失败?手把手教你解决License checkout failed问题(附详细截图)

本文针对Matlab激活后出现“License checkout failed”错误的常见问题,提供了详细的解决方案。核心在于精准定位并正确填写Windows系统用户名,而非计算机名或账户全名。文章通过分步截图和命令指引,手把手教你使用`whoami`命令获取正确信息,并重新运行激活程序,从根本上解决因用户名填写错误导致的许可检查失败问题。

weixin_29062823的博客 570

.Net在华为鸿蒙系统上的支持情况续

请先阅读前置条件:.NET既然是开源的那么可不可以把它移植到鸿蒙操作系统上?第一篇文章主要想给.Net正名,因为太多人一直在问.Net什么时候适配鸿蒙,在.net的开源仓库都看到好几个问题了,所以先写一篇文章告诉大家鸿蒙现在的技术栈.Net是完全支持的。这篇文章主要想写一些在鸿蒙上使用.Net的一些坑,顺便寻求一些帮助。问题1:跨平台编译目前我主要尝试使用NativeAot开发鸿蒙应用,众.Net...

dotNET跨平台 2262

CiteSpace基础操作(CNKI数据的导入分析)(一)

1 Cite Space简单介绍 2 文献导入 2.1 打开知网,选择高级检索

m0_50990607的博客 5万+

噪声整形与过采样实战:从N-bit ADC到DSM的SQNR优化指南

本文深入探讨了噪声整形与过采样技术在DSM(Delta-Sigma调制器)中的应用,重点分析了量化器位数(N)、滤波器阶数(L)和过采样率(OSR)对SQNR优化的影响。通过实战案例和参数协同优化策略,帮助工程师在音频处理和通信系统设计中实现更优的信号质量。

weixin_42561040的博客 339

.NET 在鸿蒙系统上的适配现状

随着全球科技格局的不断演变,操作系统作为智能设备的核心基础软件,其国产化进程成为各国科技发展的重要方向。在这一背景下,华为推出的鸿蒙操作系统(HarmonyOS)凭借其分布式架构、高兼容性和出色的跨设备协同能力,迅速成为国产操作系统领域的代表。鸿蒙系统不仅在国内智能手机市场取得了显著进展,还逐步拓展至智能家居、工业物联网、车载系统等多个领域,构建起一个完整的生态系统。在国产化浪潮的推动下,越来越多的软件平台和开发框架开始适配鸿蒙系统,以确保其在国产操作环境中的兼容性与性能表现。

2401_82505179的博客 3866

【Apollo规划模块探秘】—— 场景(Scenario)驱动的决策引擎

本文深入解析了Apollo自动驾驶平台规划模块的核心机制——场景(Scenario)驱动的决策引擎。文章通过类比日常驾驶,阐述了规划模块如何像经验丰富的司机一样,根据不同的路况(如车道跟随、无保护左转)切换不同的“驾驶模式”。重点剖析了场景管理器(ScenarioManager)如何基于感知信息进行场景判断与切换,以及“场景-阶段-任务”双层状态机如何精密协作,实现灵活、高效且安全的轨迹规划。

rnn9storyteller的博客 278

.NET 在鸿蒙系统(HarmonyOS Next)上的适配探索与实践

本文详细介绍了将.NET NativeAOT运行时适配到鸿蒙系统的完整技术方案。针对鸿蒙系统的安全限制(禁止JIT、内存执行限制等),项目团队通过修改NativeAOT源码、移植第三方库、优化内存管理等手段,成功解决了syscall限制、mmap内存申请过大、ICU初始化失败等关键技术难题。文章不仅提供了完整的适配原理和解决方案,还包含具体的源码修改指南和相关资源链接,为开发者将.NET应用迁移到鸿蒙系统提供了重要参考。目前项目已实现Avalonia框架在鸿蒙真机上的流畅运行,性能达到可用水平。

YF云飞的博客 2540

机器学习kaggle报告-Facial Keypoints Detection【完整解题过程+代码】

在处理面部关键点检测任务时,首先需要将存储在 CSV 文件中的图像数据转换为可以显示和分析的图像。数据集中每个图像是以一个一维数组的形式存储,其中包含了图像的所有像素值。为了将这些数据转化为实际的图像,我们需要按照一定的规则将这些像素值重新排列为一个二维矩阵(即图像的行列)。下面是一个案例,展示了如何将数据集中的图像数据转化为图片。转化过程读取CSV文件:首先,我们需要读取包含图像数据的 CSV 文件,通常该文件包含多张图像的像素值。每一行表示一张图像,并且包含图像的像素值列表。提取图像数据。

一键难忘的博客 3352

Labview界面多按钮控件的一种处理方法

当界面中存在多个按钮控件时候,此时如果逐个为每个控件添加事件条件则会显得较为麻烦,此处提供了一种对多控件进行批量处理的方法

miracleis的博客 2702

【鸿蒙开发实战】怎样在HarmonyOS系统源码中添加第三方软件包

说明添加成功。有很多小伙伴不知道该从哪里开始学习鸿蒙开发技术?也不知道鸿蒙开发的知识点重点掌握的又有哪些?自学时频繁踩坑,导致浪费大量时间。结果还是一知半解。所以有一份实用的鸿蒙(HarmonyOS NEXT)全栈开发资料用来跟着学习是非常有必要的。

HarmonyOS_001的博客 1819

【模型之美】3、文本聚类与智能摘要,让AI帮你做个总结

在信息过载时代,文本聚类与摘要技术成为关键工具。本文提出了一种结合OpenAI Embedding与传统机器学习的方法,实现从文本预处理到智能分析的完整流程。技术方案分为三阶段:1)通过Embedding将文本转化为语义向量;2)采用K-Means等算法进行无监督聚类;3)利用大模型生成可解释的标签和摘要。实验证明,该方法能有效提升信息处理效率,如在新闻聚合系统中自动分类10,000篇文章,准确率较传统方法提高15%。方案包含实用代码示例,涵盖文本清洗、向量化、聚类优化等关键技术细节,可应用于对话记忆、舆情

2025博客之星Top81。专注AI工程化与架构实战。从分布式思维到模型部署,用工程化视角为你厘清AI落地的真实路径。 1438
上一篇: 彻底卸载WPS Office的5种高效方法及疑难解答
下一篇: Echarts图表优化:如何智能调整grid参数让长文本完美展示
lambda
博客等级 码龄23年 49粉丝 1303原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值