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

目录

1. 前言

2. 项目状态

3. 运行时环境选择

4. NativeAOT 适配原理

4.1 底层兼容性

4.2 技术实现方案

5. 已知问题及解决方案

5.1 syscall 限制(已解决)

5.2 mmap 申请虚拟内存过大(已解决)

5.3 第三方库缺失问题(已解决)

5.4 ICU 初始化失败(已解决)

5.5 NativeAOT 跨平台编译(Windows平台已解决)

5.6 Marshal.GetDelegateForFunctionPointer 限制(已解决)

6. NativeAOT 源码修改指南

7. 相关资源


1. 前言

在当前国产化操作系统发展浪潮下,适配鸿蒙系统已成为中国软件开发的重要趋势。作为微软推出的跨平台开发框架,.NET 凭借其卓越的性能和丰富的功能库,一直被视为最优秀的客户端开发语言之一。特别是对于 Avalonia 这样的跨平台 UI 框架,能够帮助开发者快速构建高质量的桌面应用程序。在去年的 .NET Conf China 大会上,我分享了关于将 Avalonia 移植到鸿蒙系统的初步探索。经过近一年的持续努力,项目又取得了一些突破性进展。本文将系统性地整理当前遇到的所有技术问题及解决方案,希望能为正在关注 .NET 鸿蒙适配的开发者提供有价值的参考。

2. 项目状态

目前,我们已经成功实现了 .NET 在 HarmonyOS Next 系统上的基础运行能力。具体而言:

  • 基础运行时环境:已完成 .NET NativeAOT 运行时的适配工作
  • 框架适配:Avalonia UI 框架可以在 HarmonyOS Next 真机上流畅运行
  • 性能表现:经过优化后,应用程序启动速度和运行效率已达到可用水平

本文将重点探讨 .NET 运行时适配鸿蒙系统的关键技术细节,包括架构设计、问题定位和解决方案等。

3. 运行时环境选择

鸿蒙系统从 5.0.0(12) 版本开始引入了严格的安全限制:

  1. 内存执行限制:禁止匿名内存申请可执行权限
  2. JIT 限制:除系统内置的 JavaScript 引擎外,其他虚拟机均不能使用 JIT 编译功能

这些限制给 .NET 运行时的适配带来了巨大挑战:

  • CoreCLR 不可用:由于依赖 JIT 编译,无法接入鸿蒙系统
  • Mono 方案被弃用:虽然最新版 Mono 支持解释执行,但性能问题使其不适合生产环境
  • 最终选择:NativeAOT 运行时成为唯一可行的方案,通过提前编译(AOT)生成原生代码

4. NativeAOT 适配原理

NativeAOT 能够在鸿蒙系统上运行的关键在于鸿蒙的底层兼容性设计:

4.1 底层兼容性

  • libc 兼容:鸿蒙系统兼容 musl libc 的 Linux 动态库(.so)
  • RID 支持:.NET 原生支持 linux-musl-arm64/linux-musl-x64 运行时标识符(RID)

4.2 技术实现方案

  1. .NET 程序编译

    • 将 .NET 代码编译为原生 Linux 动态库(.so)
    • 导出必要的入口函数供鸿蒙调用
  2. 鸿蒙原生集成

    // 加载 .NET 生成的动态库
    void* handle = dlopen("libdotnetapp.so", RTLD_LAZY);// 获取入口函数
    typedef int (*EntryPoint)(int argc, char** argv);
    EntryPoint entry = (EntryPoint)dlsym(handle, "DotNetMain");// 调用 .NET 入口函数
    entry(argc, argv);
    

  3. 双向交互机制

    • .NET 调用鸿蒙 API
      • 通过 P/Invoke 调用鸿蒙 NDK 提供的原生接口
      • 对于 ArkUI 的 TypeScript API,通过 NDK 中的 napi 机制进行桥接
  4. 实际项目参考

    • Avalonia 移植项目:OpenHarmony.Avalonia
    • 该项目完整展示了如何将复杂的 UI 框架适配到鸿蒙系统

5. 已知问题及解决方案

5.1 syscall 限制(已解决)

问题描述

  • 鸿蒙使用 seccomp 严格限制系统调用
  • .NET 运行时初始化时会检查 NUMA 支持,调用 __NR_get_mempolicy 系统调用
  • 该调用不在鸿蒙的 seccomp 白名单中,导致进程直接被终止

技术细节

  • 鸿蒙 seccomp 白名单:app.seccomp.policy
  • 类似限制在 Android 也存在,但 .NET 对 Android 有特殊处理

解决方案: 修改 NativeAOT 源代码,将 NUMA 相关函数替换为空实现:

// 修改 numa.c
void numa_init() { /* 空实现 */ }
int numa_available() { return -1; } // 表示不支持

5.2 mmap 申请虚拟内存过大(已解决)

问题现象

  • GC 初始化时尝试申请 256GB 虚拟内存
  • 超出鸿蒙系统限制,导致 mmap 返回 Out Of Memory 错误

解决方案

方案1:环境变量控制

export DOTNET_GCHeapHardLimit=180000000000 # 限制堆大小为约180GB

方案2:源码级修改

  • 在构建配置中禁用 USE_REGIONS
  • 修改 gcenv.h 文件:
#define USE_REGIONS 0

5.3 第三方库缺失问题(已解决)

问题范围

  • ICU(国际化组件)
  • OpenSSL(加密库)
  • 其他基础依赖库

解决方案

方案1:从 Alpine Linux 移植

  • Alpine 使用 musl libc,与鸿蒙兼容
  • 阿里云镜像地址:
    • ARM64: https://mirrors.aliyun.com/alpine/edge/main/aarch64/
    • x86_64: https://mirrors.aliyun.com/alpine/edge/main/x86_64/

方案2:源码编译 对于有 CMake 支持的项目,使用鸿蒙工具链交叉编译:

cmake -DCMAKE_TOOLCHAIN_FILE=OHOS_TOOLCHAIN.cmake ..
make

5.4 ICU 初始化失败(已解决)

问题原因

  • 鸿蒙系统的 ICU 数据文件路径特殊
  • 库版本不匹配

解决方案

    1.设置环境变量:

setenv("ICU_DATA", "/system/usr/ohos_icu", 1);

    2.确保使用 libICU 72 版本:

ldd libicuuc.so.72

如果该库有cmake项目,则可以通过鸿蒙的CMake工具链编译。
 

5.5 NativeAOT 跨平台编译(Windows平台已解决)

问题描述

  • NativeAOT 默认不支持跨平台编译
  • 开发效率受限于必须在 Linux 环境下构建

解决方案: 集成 PublishAotCross 项目:

  1. 在 Windows 上编写代码
  2. 通过自动化工具链完成 Linux 环境下的交叉编译
  3. 获取最终的可执行文件

5.6 Marshal.GetDelegateForFunctionPointer 限制(已解决)

问题本质

  • 该函数依赖动态生成汇编代码
  • 违反鸿蒙的 JIT 限制

替代方案: 使用 C# 9.0 引入的函数指针特性:

delegate* unmanaged<int, void> funcPtr = ...;
funcPtr(123);

6. NativeAOT 源码修改指南

若要修改 NativeAOT 源代码并重新构建,请按以下步骤操作:

  1. 获取源码

    git clone https://github.com/dotnet/runtime.git
    

  2. 应用补丁

    • 修改 numa.cgcenv.h 等相关文件
  3. 构建命令

    ./build.sh --subset clr.aot --configuration Release -arch arm64 --cross
    

  4. 替换 NuGet 包

    • 构建产物位于 runtime/artifacts/bin/coreclr/linux.arm64.Release/aotsdk
    • 复制到 NuGet 缓存目录,如:
      C:\Users\<用户名>\.nuget\packages\runtime.linux-musl-arm64.microsoft.dotnet.ilcompiler\<版本>\sdk
      

7. 相关资源

  1. GitHub Issues 跟踪:

    • Runtime #110074
    • Runtime #111649
  2. 项目仓库:

    • OpenHarmony-NET 组织
    • Avalonia 适配项目

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

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

相关文章

图像处理--图像模板匹配NCC算法-->Fast NCC算法的解读

目录 前言 一、基础知识 二、NCC基本公式以及解决问题 1. NCC基本公式 2. 基本公式解读 三、简化分母 fuv 1. 要简化的分母 2. 积分图 3. 分母拆开化简 四、简化分子 1. 要简化的分子 2. 模板函数的近似 3. 基函数简单解释 五、Fast NCC归一化互相关值 1. 最终公…

短剧小程序系统开发:赋能创作者,推动短剧艺术创新发展

短剧作为一种新兴的艺术形式&#xff0c;具有独特的魅力和发展潜力。然而&#xff0c;在传统的发展模式下&#xff0c;短剧创作者面临着诸多限制和挑战。短剧小程序系统的开发&#xff0c;为创作者提供了强大的赋能&#xff0c;推动了短剧艺术的创新发展。创作工具丰富&#xf…

Redis知识点+项目+面试八股

基础篇&#xff1a;讲解Redis常用数据结构实战篇&#xff1a;黑马点评实战高级篇&#xff1a;Redis高级知识点原理篇&#xff1a;Redis原理面试篇&#xff1a;Redis八股⭕️第一章&#xff1a;基础篇⭕️1. Redis介绍Redis是一个key-value的数据库&#xff0c;key一般是String类…

WPS文字和Word文档如何选择多个不连续的行、段

要选择Word或WPS文字中不连续的多行、多段&#xff0c;使用鼠标加键盘即可快速搞定。Word和WPS文字中选择多行的操作一样&#xff0c;选择多段的方法略有不同。选中以后&#xff0c;可以对这些内容进行删除、复制、剪切、查找、替换、设置格式等操作。一、在Word和WPS文字中选择…

嵌入式C/C++面试大全

基础语法 1.在main执⾏之前和之后执⾏的代码可能是什么&#xff1f; main函数执⾏之前&#xff0c;主要就是初始化系统相关资源&#xff1a; 设置栈指针&#xff0c;其中栈存放的局部变量、函数参数、函数调用的返回地址初始化静态 static 变量和 global 全局变量&#xff0c;即…

Java应用架构实战指南:主流模式解析与Spring落地实践

在Java开发的世界里,选对应用架构不是纸上谈兵,而是项目成败的关键。 今天,我想和大家聊聊四种主流架构模式——分层、微服务、事件驱动和六边形架构。这些模式在实战中各有千秋,我会结合代码示例和架构图,带大家看清它们的内核。无论你是新手还是老手,这篇文章都能帮你…

重学JS-002 --- JavaScript算法与数据结构(二)JavaScript 基础知识

文章目录加入jsjs 的位置控制台变量关键字DOMbutton注释CSS转义函数参数对象属性属性访问数组Math加入js 首先创建一个 script 元素。 此元素用于将 JavaScript 加载到 HTML 文件中。 <script src"./script.js"></script>js 的位置 script 标签位于 HTML…

计算机视觉--opencv(代码详细教程)(二)

一、图片的边界填充在 OpenCV 中&#xff0c;cv2.copyMakeBorder()是用于给图像添加边框&#xff08;边缘&#xff09;的核心 API&#xff0c;其完整语法和参数说明如下&#xff1a;函数完整定义cv2.copyMakeBorder(src, top, bottom, left, right, borderType, valueNone)参数…

FPGA实现Aurora 64B66B视频点对点传输,基于GTX高速收发器,提供4套工程源码和技术支持

目录 1、前言Aurora 64B66B是啥&#xff1f;官方有Example&#xff0c;为何要用你这个&#xff1f;工程概述免责声明 2、相关方案推荐我已有的所有工程源码总目录----方便你快速找到自己喜欢的项目我这里已有的 GT 高速接口解决方案本方案在Aurora 8B10B上的应用 3、工程详细设…

【软件安装|1】CentOS7最新可用国内 yum 镜像源配置和Linux版MySQL8.0安装及其相关知识

文章目录一.更换yum镜像源二.安装并配置MySQL8.0安装配置相关知识什么是yum&#xff1f;什么是镜像源&#xff1f;相关知识请看最后&#xff0c;首先来更换yum镜像源 更换前需要准备好VmwareWorkstation和Finalshell&#xff0c;开启虚拟机&#xff0c;切换到root用户 Vmware和…

【深度学习】深度学习的四个核心步骤:从房价预测看机器学习本质

文章目录基础概念与原理第一步&#xff1a;准备数据 - 构建学习的基础数据生成与特征工程&#xff08;选择对预测有用的特征&#xff09;数据集划分的重要性第二步&#xff1a;设计模型 - 建立数学表达线性回归模型的数学表达损失函数的设计哲学第三步&#xff1a;训练优化 - 自…

Java使用Apache POI读取Excel文件

一、下载jar包 Apache POI有提供下载地址&#xff1a;Apache Archive Distribution Directory&#xff0c;直接打开链接并选择所需的版本下载即可(双击last modified可按最新更新时间排序)&#xff0c;本文章以poi-bin-4.1.1-20191023.zip为例&#xff0c;进入官网下载链接后&…

VLMs开发——基于Qwen2.5-VL 实现视觉语言模型在目标检测中的层级结构与实现方法

概述 目标检测作为计算机视觉领域的核心任务&#xff0c;传统方法依赖于 YOLO 等视觉模型对预定义类别进行位置预测。然而&#xff0c;此类方法受限于预训练类别体系&#xff0c;难以实现灵活的视觉交互。视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;的…

Spring Boot + Redis + 布隆过滤器防止缓存穿透

✅ 项目概述 在高并发系统中&#xff0c;缓存穿透 是一个经典问题&#xff1a;当恶意请求或业务逻辑查询一个数据库中不存在的 Key&#xff0c;由于缓存中也没有&#xff0c;请求会直接打到数据库&#xff0c;导致数据库压力激增&#xff0c;甚至宕机。 本项目使用 Spring Bo…

电子电路学习日记

这里的 K 表示 千欧&#xff08;kilo-ohm&#xff09;&#xff0c;而 F 在很多国产 EDA 软件&#xff08;比如立创EDA、Altium 的一些中文封装库&#xff09;里用来标注精度&#xff08;公差&#xff09;&#xff0c; F 代表 1% 精度&#xff08;英文 Fine tolerance&#xff0…

oracle 怎么实现读一致性

​ Oracle 数据块读一致性判断流程&#xff08;正确版&#xff09; 假设&#xff1a;Query SCN 查询开始的 SCN&#xff08;Query SCN&#xff09; lastSubbmit SCN 行中最新的提交scn Row SCN 行最后修改的 SCN&#xff08;存储在行头&#xff0c;通过 ITL 推导&#xff09…

ISTA为什么要加上软阈值激活函数?r若没有L1 正则化也要加其他激活函数吗?

一、加上软阈值函数&#xff08;Soft-thresholding&#xff09;是因为 LISTA&#xff08;以及它的前身 ISTA&#xff09;本质上是在求解一个 带 L1 正则化的稀疏优化问题&#xff1a; min⁡x12∥y−Ax∥22λ∥x∥1 \min_x \frac{1}{2} \|y - Ax\|_2^2 \lambda \|x\|_1 xmin​2…

线程P4 | 线程安全问题及解决方法

何为线程安全&#xff1f;要谈及何为线程安全&#xff0c;总得说来&#xff0c;我们可以用一句话来概况&#xff1a;如果在多线程环境下代码运行结果和我们预期是相符的&#xff0c;即和单线程环境下的运行结果相同&#xff0c;那么我们就称这个程序是线程安全的&#xff0c;反…

水印消失术!JavaAI深度学习去水印技术深度剖析

一、飞算JavaAI平台概述1.1 飞算JavaAI定位与技术特色 飞算JavaAI是国内领先的智能化Java开发平台&#xff0c;通过AI技术赋能软件开发全流程&#xff0c;特别针对小程序、Web应用等轻量级开发场景提供*零基础编程→高质量交**的一站式解决方案。其核心优势体现在&#xff1a; …

醋酸钆:医学影像与科技创新中的重要角色

醋酸钆是一种由钆元素和醋酸根离子组成的化合物。钆是稀土金属之一&#xff0c;常常用于医学影像、核磁共振成像&#xff08;MRI&#xff09;以及某些工业应用。醋酸钆作为钆的盐之一&#xff0c;具有许多独特的性质&#xff0c;尤其在医学和科学研究领域表现突出。一、醋酸钆的…