Rust在IOS端的入门开发

5,273 阅读3分钟

前言

阅读耗时30秒

和之前Android实现类似,基本就是一模一样,rust写完,编译拿到产物集成就行,双端接入成本而言,几乎很小。
参考资料
Building and Deploying a Rust library on iOS
cross-platform-rust example
Rust on iOS and Mac Catalyst: A Simple, Updated Guide
Rust移动开发体验

目录

Rust在IOS端的入门开发.png

一、环境准备

XCode安装

我的电脑是

MacBook Pro (13-inch, M1, 2020) macOs BigSur

选择下载了 Version 12.1 (12A7403), 没有更新

xcode-select --install

or go to xocde site XCode Download
版本支持情况见 XCode下载支持

Rustup配置

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

or you can see 安装Rust
or you can see 二、Rust入门之Hello World introduce

添加工具链

rustup target add aarch64-apple-ios armv7-apple-ios armv7s-apple-ios x86_64-apple-ios i386-apple-ios

当然没必要什么架构都编译,否则空间都不够,毕竟我的电脑只有256G,我只选择了aarch64-apple-iosx86_64-apple-ios

rustup target add aarch64-apple-ios x86_64-apple-ios

Rust项目创建及编译

第一步
crate创建

cargo new iosdemo --lib

第二步

cd iosdemo

进入到项目目录,然后开始实现代码
主要是在项目的src/lib.rs中实现rust代码,并且在目录下添加一个greetings.h头文件,作用: C 桥接文件,在这个文件中,我们定义 C 接口,确保 iOS 调用的每个 Rust 函数都在这里有定义。

企业微信截图_ca362413-861d-421f-9092-064d370592a0.png 第三步
构建我们的代码,让它能正常运行。需要在 Cargo.toml添加以下代码,然后 cargo 为我们创建一个静态库和 C 动态库。

[lib]
name = "iosdemo"
crate-type = ["staticlib", "cdylib"]

第四步
编译得到产物

cargo lipo --release

企业微信截图_a4d6e270-2ade-49ca-96b0-a100ca15840b.png

可以看到得到的产物在target目录的universal里。

企业微信截图_2b709b2b-5a3a-4556-bf49-86b88a893ebe.png

二、Rust实现

Cargo.toml
cargo帮我们创建一个静态库和 C 动态库

[package]
name = "iosdemo"
version = "0.1.0"
edition = "2021"
publish = false

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

[lib]
name = "iosdemo"
crate-type = ["staticlib", "cdylib"]

lib.rs
其中 extern 告诉 Rust 编译器这个方法将要在 Rust 以外的地方调用,确保其按照 C 的调用规则编译。

use std::os::raw::{c_char};
use std::ffi::{CString, CStr};

//no_mangle 来告诉编译器不要破坏函数名,确保我们的函数名称被导入到 C 文件
#[no_mangle]
pub extern fn rust_greeting(to: *const c_char) -> *mut c_char {
    let c_str = unsafe { CStr::from_ptr(to) };
    let recipient = match c_str.to_str() {
        Err(_) => "there",
        Ok(string) => string,
    };

    CString::new("Hello ".to_owned() + recipient).unwrap().into_raw()
}

#[no_mangle]
pub extern fn rust_greeting_free(s: *mut c_char) {
    unsafe {
        if s.is_null() { return }
        CString::from_raw(s)
    };
}

greetings.h

#include <stdint.h>

const char* rust_greeting(const char* to);
void rust_greeting_free(char *);

三、IOS 集成

集成使用

第一步
创建IosDemo工程,并导入我们之前用Rust生成的libiosdemo.a产物,

企业微信截图_26e45ccd-3601-4610-9230-3d00a1307a91.png not detailed enough ? see Building and Deploying a Rust library on iOS

第二步
接下来需要创建一个bridging header 来访问我们创建的 C 文件

  • 选择Header File 选项,创建一个bridging header ,命名为 IosDemo-Bridging-Header.h,内容如下

    //  IosDemo-Bridging-Header.h
    //  IosDemo
    //
    //  Created by xxxx on 2022/12/4.
    //
    #ifndef Iosdemo_Bridging_Header_h
    
    #define Iosdemo_Bridging_Header_h
    
    #import "greetings.h"
    
    #endif /* IosDemo_Bridging_Header_h */
    
  • 再导入我们之前创建的 greetings.h 文件

第三步
再然后就是配置编译选项了
Build your xcode project and everything should compile

企业微信截图_f37b1f1e-4d7b-4725-9340-e5af74ce16bb.png

第一个是之前写的IosDemo-Bridging-Header.h,第二个是 iosdemo/target/universal/release目录。(iosdemo是之前创建的rust项目根目录)
版本不一样,可能选项文案不太一样,可以参考 Building and Deploying a Rust library on iOS

第四步
实现
RustGreetings.swift

//  RustGreetings.swift
//  IosDemo
//  Created by xxx on 2022/12/4.
import Foundation
class RustGreetings {

    func sayHello(to: String) -> String {
        let result = rust_greeting(to)
        let swift_result = String(cString: result!)
        rust_greeting_free(UnsafeMutablePointer(mutating: result))
        return swift_result
    }
}

ContentView.swift

//  ContentView.swift
//  IosDemo
//  Created by xxx on 2022/12/4.

import SwiftUI
struct ContentView: View {
    var body: some View {
        let rustGreetings = RustGreetings()
        Text("\(rustGreetings.sayHello(to: "Rust!!"))")
            .padding()
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

效果

企业微信截图_7b001bac-b59f-44d2-9a99-f67f4ec3ffe8.png