用Rust语言开发跨iOS、Android、PC的通用算法逻辑,用FinClip小程序实现跨平台通用的业务应用前端,剩下的不通用、平台相关部分剩下一点点。
Why Rust?
因为它酷,因为个人喜欢,所以用它作为锤子,到处找钉… Nah… just kiddin’ ~
必须有一些很合理的理由。理由们如下:
- 当你开发一款应用,需要跨 iOS、Android 甚至 MacOS、Windows、Linux的时候,你可能在各平台还是用该平台相应的语言和开发框架,例如Objective-C/Swift、Java/Kotlin、Flutter、Electron 等等,实现 native的用户体验。但是不管目标平台为何,你可能有些算法性的、通用性的、底层的、无关于 UI 的代码,希望跨平台共用,开发一次但各平台编译
- 你的上述代码,例如是关于数据处理的、运算的、加解密的纯算法实现,并且对性能比较敏感。典型场景包括但不限于:设备端视频的编解码实现、设备端人工智能算法的实现、设备端系列加密相关算法的实现、设备端的文件压缩处理、设备端的数据处理、设备端 AR/VR 工具…
解决上述问题,可以采用任何操作系统都支持、几乎任何语言都能对接的 C 语言实现。可是我们知道 C 不是一种最“安全”的语言 - 线程安全、内存防泄漏… 作为一门四十年以上历史的“古早”语言,C 不是最佳选择。Microsoft 和 Linux 社区都认为,三分之二的软件安全脆弱性问题可以归结到内存安全的根源上。
能达到 C 语言级别的性能(比C++快)、又安全稳健的“现代”语言,可供选择的不多,一拍脑门想到的是 Rust。Rust 能写出这样的代码:
- 防范内存泄漏
- 实现“无所畏惧的并发”(Fearless Concurrency - 线程安全无忧)
- Runtime 极轻,编译出操作系统级别高性能原生机器码
Rust 几乎可以说要成为一把开发的“瑞士军刀”:有人拿它替代 Python 写机器学习的应用、有人拿它编译 WebAssembly 的代码跑在浏览器中、有人用它写前端 UI、有人拿它实现区块链、有人拿它写智能合约。它甚至成为 Linux 官方接受的除 C 语言之外唯一的可用于内核开发的语言。
Rust 代码在移动端运行?
用 Rust 编写、编译代码跑在设备端?没有问题。
- 首先,Android 平台官方支持采用 Rust 开发原生操作系统层面的组件(见Android Rust。
- iOS 方面,Rust编译器支持 aarch64-apple-ios、x86_64-apple-darwin 等目标架构。
另一个好消息是,在 iOS 平台上,Swift/Objective-C 代码调用 C 函数,耗损几乎可忽略不计。确实,Objective-C 本身可以被视为 C 的超集,在 Objective-C 中整合 C 的代码本身就是“纯天然”的。Rust 代码编译成 iOS 目标平台的静态库,并利用工具生成C头文件,就可以供 Swift/OC 代码集成了。
此外,对于 Swift 程序员来说,以 Swift 背景学习掌握 Rust 似乎也比其他语言背景便利,Swift 和 Rust 都是基于 LLVM 的语言,在这些年的语言进化中,Swift 的设计也受到 Rust 的启迪,网上有不少同时掌握 Swift 和 Rust 的程序员,这里就有人比较了两种语言的特征。
一个理想的跨设备端架构是:Core + Platform Wrapper -
Core:基于Rust实现的核心算法(数据处理、加解密、网络并发、本地嵌入式存储、机器学习…)
Platform Wrapper:所在设备的人机交互以及其他应用层组件的粘合、集成。Wrapper 的具体实现技术就多了去了,包括但绝不限于这些:
- Desktop(Linux/Windows/Mac):Qt、Electron
- iOS:OC/UIkit、Swift/SwiftUI
- Android:Java/Kotlin
基于 Rust 写出来的 core,在上述操作系统都能编译运行(首先感谢 LLVM,然后是如果你妥善使用 Rust 以及其相关工具链例如 cargo 的话)。Rust 适用于“原创” - 即你自己“手写”的代码,如果这些代码主要是以一定的数据结构与算法实现的逻辑,它们没有什么理由不能跨平台。
但如果你写的代码主要是一些第三方网络服务、REST 接口集成的“glue
code”,即粘合型代码,则这种代码是否有称得上“core”或者是否有必要独立存在而不是融合至 wrapper 中,就有待商榷了。
夹心饼架构:两头通用、中间稳定
假设我们用 Rust 写出了一个跨平台的通用的 core,并且我们也非常轻易的就构建PC/Mac、iOS、Android(手机、IoT/智能设备)上的 wrapper,为了降低开发成本、实现应用逻辑开发一次即可在多个平台运行,还可以更进一步做点什么呢?
拦路虎是人机交互(UIUE)部分,当前业界也有各种方案选择:
- JavaScript/React-Native:让开发者只需要懂 JavaScript 和React,即可开发出一个目标平台的应用,原理是让 JavaScript 代码通过 bridge 调用平台的原生接口和原生 UI 组件
- Dart/Flutter:开发者用 Dart 语言开发应用,其 runtime 既不使用 JavaScript bridge 也不使用 JIT,而是通过 binary messaging channel 去和目标平台原生部分的代码建立双向的通讯流,结合AOT(ahead-of-time)编译,实现高效能。Flutter 自带的 UI 框架与组件(通过自带的 2D 渲染引擎 Skia实现),也消除异构技术调用目标平台原生 UI 的耗损,并且能让开发者开发出更加灵活多变的 UI(例如 Apple UXguidelines 所不支持的设计)
- 小程序FinClip:开发者只要懂微信小程序、支付宝小程序或者任何互联网上流行的小程序开发,即可实现 UIUE,让自己的 App 变成一个运行小程序的载体。需要做的事情,是把 FinClip SDK,一个专门远程加载、解析、安全运行小程序的安全沙箱及渲染引擎,打包嵌入到自己的 App中,然后把应用逻辑的人机交互部分,以小程序的方式进行开发。小程序这类技术,目前正在 W3C 的 MiniApps workgroup形成互联网标准,它也可以被理解为一种更加遵循 HTML5、更加充分利用现有技术标准的方案,和传统的 PWA(Progressive WebApp)相比,它更加适合在移动端和 IoT 设备运行。
FinClip 小程序有所不同
其中 FinClip 小程序的方案,和前二者其实不见得特别适合对比,不是一个门类。
- 首先 FinClip SDK 可以嵌入在以这二者开发的 App 中,从而让 App获得小程序的运行能力;
- 其次 FinClip 试图解决的不仅是一个“跨终端开发”、“敏捷开发”这样的问题,它的根本目标是:让 App的拥有者建立自己的小程序生态、和自己的客户以及合作伙伴实现数字化资源整合与数字化连接,所以 FinClip 是一个“端侧运行沙箱” +“云侧应用市场”的解决方案,它的云侧实际上是一个你可以私有化部署的开发者中心以及小程序上下架管理的应用生态运营工具;
- 最后,FinClip 技术也不约束开发者使用何种 JS 开发框架,无论 react/taro 还是 uni-app/vue,能开发出微信小程序的都可以。
这样的话,我们可以尝试一个这样的“夹心饼”架构,把各平台原生的差异化部分放在中间并压缩它负责的范围,在上下两侧利用通用化技术分别实现人机交互和核心算法:
利用 FinClip 技术,我们就可以轻易打造一款跨 iOS、Android(和其他主流操作系统)的设备端应用,具备运行各种小程序的能力,并让这些小程序利用到以 Rust 语言开发的跨硬件、跨操作系统的原生功能。
Rust 函数供小程序调用?
用 Rust 实现一些计算类的功能(例如一个存储密钥的加密货币钱包),如何在设备端让小程序调用(例如构建一个加密货币钱包或者DeFi应用的管理界面)?
要做的事情如下:
- 把 FinClip SDK 集成到 App 中
- 把 Rust 代码编译成目标架构下的静态库,并生成 C 的头文件 把上述静态库打包至 App 中
- 把 Rust 代码中的函数,注册至 FinClip SDK 开发小程序,使用上述函数实现所需的小程序功能
- 利用FinClip.com 的公共平台以及 IDE,对自己的 App 以及小程序进行测试,发布上架