• q2_677927
  • 296.3KB
  • zip
  • 0
  • VIP专享
  • 0
  • 2022-04-15 11:37
适用于本机Android和iOS应用程序的Rust核心 [ iOS徽章] 此示例显示了如何在本机Android和iOS应用程序中使用共享的Rust核心。 为什么? 这种方法为我们提供了最好的解决方案:我们通过使用共享库来防止代码重复。 Rust是一种高性能且安全的语言,非常适合移动设备使用。 我们保留了完全本机的UI体验,并且可以轻松访问平台的最新API。 它也非常灵活,可以轻松地在不同平台之间迁移,包括Flutter或React Native等常规跨平台框架。 例如,您可以使用Rust + React Native或Rust + Flutter开发MVP,然后再迁移到本机iOS / Android,而无需重写所有内容。 您甚至可以使用WebAssembly或桌面应用程序(在这里,您可以使用本机或跨平台框架,例如Electron)将您的核心重用于Web应用程序。 项目结构 Rus
# Rust core for native Android and iOS apps ![logos](img/logos_.png) ![Rust]( ![Android]( [[TODO]( iOS badge] This is an example that shows how to use a shared Rust core in native Android and iOS apps. # Why? This approach gives us the best of all worlds: we prevent code duplication by using a shared library. Rust, as a highly performant and safe language is a great fit for mobile. We keep a fully native UI experience and uncomplicated access to the latest APIs of the platforms. It's also very flexible, allowing to migrate easily between different platforms, including conventional cross-platform frameworks like Flutter or React Native. For example, you can develop your MVP with Rust+React Native or Rust+Flutter, and migrate later to native iOS/Android, without having to rewrite everything. You even can reuse your core for a web-app, using WebAssembly, or desktop app (where again, you can use native or a cross-platform framework like Electron). # Project structure - Rust: Repo's root. - iOS app: `ios_app` directory. - Android app: Repo's root as well. TODO move it to a folder `android_app`, like the iOS app. # Possible setups There are different ways to integrate Rust: ## As source (like in this repo) - Simple setup. - Rust is built as part of the app's build process. - Not ideal if there are team members unfamiliar with Rust. ## As binary The Rust binary is distributed as an external dependency. - Better for teams with different skillsets. Everyone works mainly with their familiar tech stack. - Better separation of concerns / modularity. - Considerably more complicated to setup than monorepo (has to be done only once though). - Rust binaries have to be versioned and released. Note: it is possible to overwrite the external dependency with a local copy for local development. ## As "normal" library Here the external dependency contains the Rust binary and wrapper libraries for Android and iOS respectively (written in Kotlin and Swift), which hide the FFI/JNI, providing a simple and safe interface to the apps. This makes working with this dependency like with regular third parties. An example for this and the binary approaches can be found [here]( The Android build contains a wrapper library, which is imported in the Android app with [Gradle]( The iOS build is distributed directly as a binary (no wrapper), using [Carthage]( # Note on asynchronous tasks and reactive programming While it's possible to use asynchronous code in core, it's recommended to write it synchronously and execute it asynchronously / with reactive programming in the apps. This greatly simplifies things (see the [CoEpi]( example, which uses Rx in the apps). # "Real world" examples ### [CoEpi]( A mobile contact tracing app for epidemics, with [Android]( and [iOS]( frontends. ### [Xi editor]( A text editor with a lot of frontends: MacOS, GTK, Electron and Windows, among others. # Other related projects ### [WASM-Rust-d3 example]( An example that shows how to display chart data with d3/JS, using a Rust core to fetch it. ### [yew-d3-example]( Similar to the above, but using the [Yew framework]( # Quickstart Install [rustup]( ## Android specific steps - Ensure the [NDK]( is installed. - Set the NDK_HOME environment variable with path to the NDK, e.g: ``` export $NDK_HOME=$HOME/Library/Android/sdk/ndk/21.3.6528147/ ``` - Install [cargo ndk]( ``` cargo install cargo-ndk ``` - Add targets ``` rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android i686-linux-android ``` - Run the project in Android Studio. This will build Rust, put the binaries in the correct place and start the app. ## iOS specific steps - Add targets ``` rustup target add x86_64-apple-ios aarch64-apple-ios ``` - Run the project in Xcode. This will build Rust, put the binaries in the correct place and start the app. ## Android specifics - Logcat doesn't show stdout and stderr, which means that you'll not see `println` or `panic` messages (unless specially configured, like done in this repo). - If you're having difficulties, try reproducing the problem in a plain (non Android) Kotlin (or Java) project. The JNI is the same, but it's easier to debug, among other things, because you can see stdout/stderr. ## iOS - iOS shows stdout/stderr as expected and is overall easier to worth with than Android, given the simpler FFI api. ## Inspecting binaries There are diverse tools to inspect the binaries, e.g. ``` nm -g ``` Shows the external symbols, useful if you want to check that the library was generated correctly / contains the symbols from your sources. To look for a specific symbol: ``` nm -g | grep greet ``` # Convenience ## iOS - [cbindgen]( generates headers for the FFI Rust declarations. In this project, this would mean that `mobileapp-ios.h` would be automatically generated. ## Android - [rust-swig]( similarly to cbindgen for iOS, this generates the JNI api for the Rust declarations. In this project, this would mean that `JNIApi` would be generated, and `` mostly too. You'd have to write no JNI. I _personally_ recommend against this, at least for the beginning, as it's better to understand what's going on and JNI, while tedious, is not so complicated. # Links [Official Rust FFI docs]( [Rust FFI guide]( [Official JNI docs]( (tutorials may be better to start...) [Android JNI tips]( [Android supported ABIs]( # Contribute 1. Fork 2. Commit changes to a branch in your fork 3. Push your code and make a pull request