Rust在移动开发中的跨平台应用:iOS与Android支持状态及开发模式解析

2024-12-29
来源:网络整理

介绍

Rust在服务器和嵌入式领域已经有很多跨平台的应用案例。本文主要探讨Rust在移动开发领域的跨平台开发模型。

本文涉及的所有信息均来自互联网。如有错误或遗漏,请及时反馈。

iOS 和平台的 Rust 语言支持状态

目前,Rust 支持 iOS 和平台的 Tier 2 和 Tier 3 级别,并且都支持 std。

支持 iOS:

第 2 级:

第 3 级:

支持:

第 2 级:

可见Rust对iOS和iOS的支持还是相当不错的。

Rust 使用跨平台组件进行移动开发的几种方式

一些公司使用 Rust 来开发跨平台组件,即在 iOS 和 之间共享代码。

对于iOS,Rust可以直接通过FFi绑定C-ABI进行交互。您可以参考这篇最近发布的文章来了解如何在 iOS 应用程序中部署 Rust 库。对于 Rust,JNI 相关的库用于相关绑定。 Rust 社区生态系统也有一些类似于 -ndk-rs 的用于 NDK 开发的工具。

这种模式可以称为:App-Rust后端(App-Rust)。当然,Rust也可以编译并共享到浏览器(应用条件比客户端相对严格)或桌面(例如)。

公司:

为什么不使用Cpp来共享代码呢?

或许你可以从2019年发表的《iOS和之间共享代码的隐性成本》一文中看出问题:Cpp共享代码会带来四类隐性成本。总结如下:

如果编写一次代码并在各处重用它的成本超过了收益,则无需使用此策略。所以,又回到使用本地语言进行移动开发,直到 2022 年。今年 3 月的一篇博客也解释了这种情况:让相机上传更快、更可靠。

桌面客户端使用Rust开发跨平台组件

虽然在移动领域,放弃了使用Cpp共享代码的策略,但也没有使用Rust。然而,在 2021 年,另一个团队使用 Rust 构建了其桌面客户端的跨平台同步引擎组件。是一种视觉通信工具,旨在让团队可以轻松地使用屏幕录制、视频消息、屏幕截图或 GIF 异步共享他们的工作。

为什么使用 Rust?

一方面,Rust在我们的产品中使用越来越广泛,团队的经验也得到了提升;另一方面,Rust 本身就非常适合这种场景,我们希望能够更好地控制截图和录制能力、更好的错误处理以及更快的幕后性能。

使用 Rust 的好处:

根据以上实践,你可以对Rust vs Cpp在跨平台共享组件方面的优缺点有一定的了解。接下来我们看看其他公司的做法。

公司:

该公司提供数字体验智能(DXI)平台并提供数据分析服务。该平台还为移动应用程序提供数据收集功能,并使用 Rust 开发跨平台组件。

为什么选择 Rust?

当前的移动生态系统主要由iOS和设备组成。任何想要接触大多数移动用户的人都会发现自己必须开发两个版本的应用程序。

两个平台之间存在显着差异:在语言层面,iOS 应用程序主要是用(历史上是 ObjC)编写的;另一方面,应用程序主要是用Java编写的,Java在当今越来越流行。由于平台对现代移动应用程序想要执行的所有操作(从创建按钮小部件到地理定位)都有不同的抽象,因此随着业务的增长,维护两种不同语言的版本变得越来越困难。

公司面临的问题可能更复杂,因为他们提供框架供其他人使用,而不是直接发布应用程序。因此,请考虑技术选择对客户的影响,例如与其代码进行有害交互的可能性,以及用户在 CPU 和内存使用方面可见的性能影响。

如何使用 Rust?

首先制定了一个粗略的设计指南:Rust 代码应该包含与平台无关的通用代码,而特定于平台的代码应该保留在特定于平台的代码中。

代码组织结构:

对于 iOS,将 Rust 代码构建为静态库,并使用一致版本的 LLVM 使用脚本构建 Rust 工具链。

为此,Rust 被构建为静态库,与一些 C 代码链接,然后与 Java 库共享。

未来使用 Rust 的优势

能够编写高性能代码,而无需花费太多时间进行优化

无需在平台提供的 Rust 代码中追踪客户报告的数据竞争导致的奇怪崩溃或错误

不熟悉平台代码库的开发人员可以充满信心地加入,因为他们知道编译器将限制他们因不完全理解“烙印”在他们大脑中的代码而造成的损害。 (Rust语言比较流行,新人也愿意学习)

在移动开发中使用Rust有哪些痛点?

工程师上面透露:

“我们感受到的唯一真正的痛苦是 iOS,如果你不这样做,他们就会这样做。”

“我们唯一真正的痛苦是 iOS 的位码,这主要是苹果的错,因为如果你不使用它,他们会让整个过程变得非常复杂。”

此问题记录在 Rust:(未解决)中,导致团队无法直接使用上游 Rust 工具链。他们的解决方案是使用相同版本的 LLVM 提供嵌入 LLVM 位代码的框架。

公司:

现在也加入 Rust 基金会。其产品大约63%的核心代码(加密和同步数据)使用Rust。用 Rust 开发的跨平台组件支持多个平台,包括移动设备和浏览器(编译为 Rust)。但将此方法称为“() 应用程序开发”。

一些跨平台库也是开源的。例如sys-,一个轻量级的获取位置的跨平台库,支持iOS/////。还有一个早期的开源库,用于将一些用Rust编写的类型生成为其他语言的相应类。它不再维护,但仍在公司内部使用。

下图为该版本下核心相关架构。

首先,这个核心库是一个完全独立的Rust库,它定义了清晰的API供各种客户端使用。

op-app 和 op-ui 用于集成其他应用。大多数状态完全保留在内部,确保正确处理密钥和其他内容,同时也允许每个客户端 UI 专注于自己的优势而不是业务逻辑。为核心提供特定于平台的服务(OS)。 ETC。

目前这个通用核心库在终端上是比较成功的,团队表示在下一代产品中也会采用这个架构。

有趣的事实:

请阅读 2019 年的一篇论文,该论文探讨了流行密码管理器的安全最佳实践,包括。并且同年,关于论文中提到的1P的安全问题,在1P社区论坛上引起了热烈的讨论。 1P成员也首次提到了Rust语言。也许这就是使用 Rust 的 1P 的开始。现在他是 Rust 基金会的成员。

公司:字节跳动飞书

关于飞书使用 Rust 的公开信息很少。只有字节跳动王聪在2019年QCon上分享的《字节跳动Rust跨平台客户端开发实践》,从中我们可以了解到,飞书也使用Rust来做跨平台组件。飞书客户端的非UI部分采用Rust跨平台实现,目前包括移动端、桌面端等共5个平台。

为什么使用 Rust 跨平台?

客户端开发有一定的复杂度

几乎是一个整体架构

底层代码的安全保障较少

在有限的资源内满足不断增长的需求

需要更少的功耗来满足不断增长的需求

性能要求

实施复杂度

平台之间存在差异,团队不想重复工作并犯同样的错误。

考虑跨平台可以带来的好处:

如何实现跨平台:

语言选择:

飞书架构:

如图所示,基本架构是通过线程池来管理不同的线程进行交互。

Rust 进程和 /Java/ 是通过 FFi 和(类似于 RPC)调用的。

Rust库的模块组织如下:

每个都是独立构建、运行、测试和依赖的。底层的内容不会经常改变。

使用的Rust技术栈是:

遇到的问题:

优化编译文件大小

Rust LLVM 和 的 LLVM 版本不同并且有点不兼容(与公司的问题相同)

提供的免费优质游戏:

是一款适用于 、iPad 和(通过 Mac)的 () 应用程序,并荣获 2022 年 2 月精选游戏和 2021 年最喜爱游戏荣誉。

作者在博文中讨论了 Rust 是否是一种更适合编写游戏 AI 模块的语言。

博文要点总结:

开源产品:

它是一个类似于 .但它更灵活。用户不仅可以DIY自己的域名和页面外观,还可以跨多个平台使用。

虽然飞书使用 Rust 开发跨平台组件的细节尚不清楚,但据飞书开发成员介绍,其应用思路应该与 .

使用Rust和开发,官方也通过文章介绍了整体架构。

前端和后端服务都使用 Rust。这里我们主要讲一下前端架构。

前端架构采用领域驱动设计(DDD)的理念,采用分层架构。

DDD,简单来说,就是将业务架构映射到系统架构上,能够充分隔离业务和技术的界限。业务和技术实现的隔离一般通过分层架构和六边形架构来实现。

分层架构:遵循“关注点分离”的原则进行分层,将属于业务逻辑的关注点放入领域层( ),将支持业务逻辑的技术实现放入基础设施层( )。还有一个应用层( ),一方面通过暴露业务应用服务的API作为业务( )的逻辑门面,另一方面是业务和技术实现之间的粘合剂。

六边形架构(端口适配器):遵循“内外分离”原则分层。内部代表应用程序的业务逻辑,外部代表应用程序的驱动逻辑、基础设施和UI/DB等其他层。这更加清晰地勾勒出了业务逻辑和技术实现之间的界限,并将业务逻辑置于架构的核心。地点。体现业务逻辑的应用层和领域层是六边形架构的核心,通过内部六边形边界与基础设施模块隔离。开发软件时,只要坚守架构的六边形边界,技术实现的复杂性就不会污染业务逻辑,保证了领域的整洁。如果我们在领域层或者应用层抽象出技术实现的接口,然后通过依赖注入来反转控制方向,那么业务核心就会变得更加稳定,不会因为技术选型或者其他决策的变化而导致领域代码发生变化。修改。

前端架构分为两部分:

数据组件:负责数据相关逻辑。根据DDD分层架构,它是基础设施层。基于Rust实现。

抽象级别从基础设施层到表示层逐渐增加,复杂性则向相反方向发展。

如何跨平台

例如,通过实现实现跨平台:在 中定义接口,在 Rust 中实现接口,然后通过 Dart FFi 绑定 Rust 实现并使用事件分发机制。

该模型的优点是:

缺点:

DDD架构整体业务处理流程

流程如下:

表示层的 UI 小部件与用户交互,并将这些交互转移到特定的 Bloc 事件中。 Bloc发回事件引起的变化,最后根据新的状态更新用户界面。这里的Bloc代表DDD中的应用层,它使用领域层提供的资源库或服务来处理Bloc事件。

将数据传递到下一层。

其中定义了实现其业务需求的接口和数据模型。数据模型是使用 Rust 来描述数据模型而生成的。使用可以更轻松地将数据从 Rust 端转换为 Rust 端,反之亦然,但序列化和反序列化是有代价的。一般是没有问题的,但是有时候处理图片的时候会出现内存问题,不过这个是可以优化的。

将请求序列化为二进制数据并传递给它。

() 找到请求的处理程序,然后使用其数据调用它。每个模块都声明它可以处理哪些事件,并向调度程序注册自己。

处理程序会根据事件提取二进制数据并将其反序列化为特定的数据结构并执行一些业务逻辑。

将返回值序列化为二进制数据并发送给调度器。

响应包含状态代码,二进制数据作为返回值()传递给调用者。

将二进制数据反序列化为特定的 Dart 对象。

将对象传播到上层

Bloc 等待完成并在状态发生变化时重建。

有关的

作者也在和开发者沟通,以后可能会使用,但目前进度比较慢。

开源项目:

它是一个开源的现代跨平台遥测()库。提供SDK支持Rust/////QML等多种语言和开发环境。其中,Rust///SDK是基于Rust核心库构建的,/QML是基于核心库构建的。

(遥测技术)一般是指从物理网元或虚拟网元远程实时高速采集数据,实现对网络的实时、高速、更精细的监控。

跨平台支持:

使用 -rs 通过编写接口定义语言(基于)文件来描述目标语言中可用的方法和数据结构,自动生成 Rust 库 FFi 绑定。然后就可以生成/绑定了。

跨平台开源框架和游戏引擎

除了使用 Rust 开发跨平台共享组件之外,Rust 生态系统中还有一些框架和游戏引擎可以帮助您实现跨平台应用程序和游戏。

图形用户界面框架:

主要用于开发桌面平台,更加轻量级,性能更好。它允许开发者利用各个平台的技术栈,通过JS API调用后端接口。目前支持 // 等平台,iOS/移动平台的支持正在进行中。

8 使用开发引起了很多用户的不满。由于占用资源过多,因此还存在内存泄漏问题和安全风险。用户认为它只是一个密码管理软件,不应该占用太多的系统资源。也许将来它会是一个很好的替代品。

建筑学

主要由两大部分组成:

Tool,外部工具库

其他

跨平台支持

-app/tao利用Rust的and机制完美实现了跨平台架构:

使用统一的等窗口抽象:

// Window 抽象
pub struct Window {
  pub(crate) window: platform_impl::Window,
}

// Clipboard 抽象
#[derive(Debug, Clone, Default)]
/// Object that allows you to access the `Clipboard` instance.
pub struct Clipboard(ClipboardPlatform);

// EventLoop 抽象
pub struct EventLoop'static> {
  pub(crate) event_loop: platform_impl::EventLoop,
  pub(crate) _marker: ::std::marker::PhantomData<*mut ()>, // Not Send nor Sync
}

在内部,模块负责调用各个平台的具体实现:

#[cfg(target_os = "windows")]
#[path = "windows/mod.rs"]
mod platform;
#[cfg(any(
  target_os = "linux",
  target_os = "dragonfly",
  target_os = "freebsd",
  target_os = "netbsd",
  target_os = "openbsd"
))]

#[path = "linux/mod.rs"]
mod platform;
#[cfg(target_os = "macos")]
#[path = "macos/mod.rs"]
mod platform;
#[cfg(target_os = "android")]
#[path = "android/mod.rs"]
mod platform;
#[cfg(target_os = "ios")]
#[path = "ios/mod.rs"]
mod platform;

对于-app/wry来说,跨平台架构的实现与tao类似。

构建统一的跨平台抽象:

// WebView 抽象
pub struct WebView {
  window: Rc,
  webview: InnerWebView, 
}

pub struct WebViewBuilder<'a> {
    pub webview: WebViewAttributes,
    web_context: Option<&'a mut WebContext>,
    window: Window,
}

impl<'a> WebViewBuilder<'a> {
    pub fn build(self) -> Result {
        let window = Rc::new(self.window);
        let webview = InnerWebView::new(window.clone(), self.webview, self.web_context)?;
        Ok(WebView { window, webview })
    }
}

内部部分是平台特定的行为代码,用于通过cfg构建统一的门面模块,完成跨平台分发。

#[cfg(target_os = "android")]
pub(cratemod android;
#[cfg(target_os = "android")]
use android::*;
#[cfg(any(
  target_os = "linux",
  target_os = "dragonfly",
  target_os = "freebsd",
  target_os = "netbsd",
  target_os = "openbsd"
))]

pub(cratemod webkitgtk;
#[cfg(any(
  target_os = "linux",
  target_os = "dragonfly",
  target_os = "freebsd",
  target_os = "netbsd",
  target_os = "openbsd"
))]

use webkitgtk::*;
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub(cratemod wkwebview;
#[cfg(any(target_os = "macos", target_os = "ios"))]
use wkwebview::*;
#[cfg(target_os = "windows")]
pub(cratemod webview2;
#[cfg(target_os = "windows")]
use self::webview2::*;

可见,使用Rust进行跨平台开发非常简单。

游戏引擎:Bevy

Bevy是一个数据驱动的游戏引擎,目前在社区中拥有很高的声誉,并得到了许多公司的赞助。 Bevy 也是跨平台的,在主流桌面操作系统 (,,,) 上开箱即用,无需任何特殊配置。 Bevy 还针对 Web 浏览器(已通过,但有一定限制)、移动设备(和 iOS,可以构建但不一定运行)和游戏控制台(待支持)。

跨平台支持

Bevy本身抽象程度比较高,跨平台支持主要依赖一些底层库:

这些底层库的跨平台模式与上面的架构类似。

一些移动开发工具介绍

- 是一个独立于框架的工具,可以生成Rust移动项目的所有样板文件,并包含大量用于在移动设备上构建和运行的便捷命令,可以提高Rust在移动领域的开发体验。目前仅支持 和 .

ndk-rs,NDK 的 Rust 绑定库。该库广泛应用于 Rust 移动生态系统中。基本用于上述公司的产品和项目中。

支持 Rust 的官方方式

自 2019 年以来,该团队一直致力于将 Rust 编程语言引入开源项目(AOSP)。 2021 年 4 月, 宣布开源项目 (AOSP) 现在支持 Rust 编程语言进行操作系统开发。

关键信息摘录:

一封公开信:请将 -C 替换为 Rust

Labs CEO( )去年(2021.10)在官网发表公开信:请将-C替换为Rust。文章摘要:

虽然工作量很大,但投资回报率却很高。迁移到 Rust 可以消除 70% 的漏洞,并且可能接近 95% 的可远程利用的漏洞。专注于解析来自不可信来源的数据的库将使平台更加安全。

参考

%E7%A7%BB%E5%8A%A8%E6%96%B0%E7%94%9F%E6%80%81

分享