国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Flutter調(diào)用Rust代碼操作指南

這篇具有很好參考價(jià)值的文章主要介紹了Flutter調(diào)用Rust代碼操作指南。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

Flutter調(diào)用Rust代碼操作指南

在之前的利用Rust與Flutter開發(fā)一款小工具文章中,我們使用Rust代碼實(shí)現(xiàn)了一個(gè)簡單的WebSocket發(fā)送功能。也在Rust庫交叉編譯以及在Android與iOS使用這篇中介紹了Rust庫的打包以及雙端的使用。

今天我們繼續(xù)用之前WebSocket的代碼舉例,來介紹如何在Flutter項(xiàng)目中使用。

準(zhǔn)備工作

本篇的主角就是flutter_rust_bridge,它是用于 FlutterRust 的高級(jí)內(nèi)存安全綁定生成器。這個(gè)庫只是一個(gè)代碼生成器,幫助你的 Flutter / Dart 調(diào)用 Rust 函數(shù)。它只是生成了一些模板代碼,代替了手工編寫。

首先我們可以把Rust代碼放到Flutter項(xiàng)目的根目錄中,或者運(yùn)行 cargo new --lib創(chuàng)建一個(gè)新的 Rust crate。完成后項(xiàng)目結(jié)構(gòu)如下:

├── android
├── ios
├── lib
├── linux
├── macos
├── $crate
│   ├── Cargo.toml
│   └── src
├── test
├── web
└── windows

注意:將 crate 的根目錄設(shè)為和其他項(xiàng)目同等級(jí)別,這樣有助于簡化配置過程。

稍微修改一下之前的rust代碼(注意代碼不要直接寫在lib.rs中,不然生成文件無法獲取導(dǎo)包):

這里我們將之前的代碼放入api.rs中:

use std::collections::HashMap;
use std::sync::Mutex;
use ws::{connect, Handler, Sender, Handshake, Result, Message, CloseCode, Error};
use ws::util::Token;


lazy_static! {
    static ref DATA_MAP: Mutex<HashMap<String, Sender>> = {
        let map: HashMap<String, Sender> = HashMap::new();
        Mutex::new(map)
    };
}

struct Client {
    sender: Sender,
    host: String,
}

impl Handler for Client {
    fn on_open(&mut self, _: Handshake) -> Result<()> {
        DATA_MAP.lock().unwrap().insert(self.host.to_owned(), self.sender.to_owned());
        Ok(())
    }

    fn on_message(&mut self, msg: Message) -> Result<()> {
        println!("<receive> '{}'. ", msg);
        Ok(())
    }

    fn on_close(&mut self, _code: CloseCode, _reasonn: &str) {
        DATA_MAP.lock().unwrap().remove(&self.host);
    }

    fn on_timeout(&mut self, _event: Token) -> Result<()> {
        DATA_MAP.lock().unwrap().remove(&self.host);
        self.sender.shutdown().expect("shutdown error");
        Ok(())
    }

    fn on_error(&mut self, _err: Error) {
        DATA_MAP.lock().unwrap().remove(&self.host);
    }

    fn on_shutdown(&mut self) {
        DATA_MAP.lock().unwrap().remove(&self.host);
    }

}

pub fn websocket_connect(host: String) {
    if let Err(err) = connect(host.to_owned(), |out| {
        Client {
            sender: out,
            host: host.to_owned(),
        }
    }) {
        println!("Failed to create WebSocket due to: {:?}", err);
    }
}

pub fn send_message(host: String, message: String) {
    let binding = DATA_MAP.lock().unwrap();
    let sender = binding.get(&host.to_owned());
    
    match sender {
        Some(s) => {
            if s.send(message).is_err() {
                println!("Websocket couldn't queue an initial message.")
            };
        } ,
        None => println!("None")
    }
}

pub fn websocket_disconnect(host: String) {
    DATA_MAP.lock().unwrap().remove(&host.to_owned());
}

api.rs

mod api;
#[macro_use]
extern crate lazy_static;

Cargo.toml配置如下:

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

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

[profile.release]
lto = true
opt-level = 'z'
strip = true
codegen-units = 1
# panic = 'abort'

[dependencies]
ws = "0.9.2"
lazy_static = "1.4.0"
flutter_rust_bridge = "=1.77.1"
flutter_rust_bridge_macros = "=1.77.1"

[build-dependencies]
flutter_rust_bridge_codegen = "=1.77.1"

Flutter中pubspec.yaml的配置如下:

dependencies:
  flutter_rust_bridge: 1.77.1
  ffi: ^2.0.1

dev_dependencies:
  ffigen: ^8.0.2

這里注意flutter_rust_bridge的版本需要一致。我這里目前使用的是1.77.1。然后在rust項(xiàng)目中執(zhí)行:

cargo install flutter_rust_bridge_codegen
# 如果為iOS或MacOS應(yīng)用構(gòu)建
cargo install cargo-xcode
  • flutter_rust_bridge_codegen, 生成 Rust-Dart 膠水代碼的核心。
  • ffigen, 從 C 頭文件中生成 Dart 代碼/
  • 安裝 LLVM, 請(qǐng)看 Installing LLVM,ffigen 會(huì)使用到。
  • (可選) cargo-xcode,如果你想生成為 IOS 和 MacOS 的 Xcode 項(xiàng)目。

完成上面的準(zhǔn)備工作,我們就可以在Flutter項(xiàng)目下執(zhí)行命令,成功膠水代碼了。

flutter_rust_bridge_codegen -r native/src/api.rs -d lib/ffi/rust_ffi.dart -c ios/Runner/bridge_generated.h
  • native/src/api.rs rust代碼路徑。
  • lib/ffi/rust_ffi.dart生成dart代碼路徑。
  • ios/Runner/bridge_generated.h創(chuàng)建的一個(gè) C 頭文件,里面列出了 Rust 庫導(dǎo)出的所有符號(hào),我們需要使用它確保 Xcode 不會(huì)將符號(hào)去除。

Android配置

首先安裝cargo-ndk,它能夠?qū)⒋a編譯到適合的 JNI 而不需要額外的配置。我們之前的文章中,就通過手動(dòng)的方式在.cargo/config中配置clang鏈接器的路徑。就比較繁瑣,這個(gè)插件就是簡化這一操作的。

安裝命令:

// ndk低于22
cargo install cargo-ndk --version 2.6.0
// ndk高于22
cargo install cargo-ndk

交叉編譯到安卓需要一些額外的組件,這個(gè)我們之前的文章也有說明:

rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android

接著,在 android/app/build.gradle 的最后添加下面幾行:

[
        Debug: null,
        Profile: '--release',
        Release: '--release'
].each {
    def taskPostfix = it.key
    def profileMode = it.value
    tasks.whenTaskAdded { task ->
        if (task.name == "javaPreCompile$taskPostfix") {
            task.dependsOn "cargoBuild$taskPostfix"
        }
    }
    tasks.register("cargoBuild$taskPostfix", Exec) {
        workingDir "../../native"
        environment ANDROID_NDK_HOME: "$ANDROID_NDK"
        commandLine 'cargo', 'ndk',
                // the 2 ABIs below are used by real Android devices
                '-t', 'armeabi-v7a',
                '-t', 'arm64-v8a',
                '-o', '../android/app/src/main/jniLibs', 'build'
        if (profileMode != null) {
            args profileMode
        }
    }
}
  • ../../native就是rust代碼路徑。
  • ANDROID_NDK就是在android/gradle.properties配置的NDK路徑。
  • Android每次運(yùn)行都會(huì)打包rust代碼并將so文件放入android/app/src/main/jniLibs下。所以如果Rust代碼沒有變化修改,可以在生成release文件后注釋掉此處代碼。
ANDROID_NDK=/Users/weilu/android/android-sdk-macosx/ndk/21.4.7075529

iOS配置

安裝交叉編譯組件:

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

接著在rust項(xiàng)目目錄下執(zhí)行cargo xcode。執(zhí)行后,會(huì)生成一個(gè)xcodeproj后綴文件夾。它可以用于導(dǎo)入到其他 Xcode 項(xiàng)目中。
Flutter調(diào)用Rust代碼操作指南
在 Xcode 中打開 ios/Runner.xcodeproj, 點(diǎn)擊菜單File ---> Add Files to "Runner"接著把 xxx.xcodeproj 添加為子項(xiàng)目。

  • 點(diǎn)擊 Runner 根項(xiàng)目,在Build PhasesTab下的Target Dependencies點(diǎn)擊加號(hào)添加 $crate-staticlib文件。
    Flutter調(diào)用Rust代碼操作指南
  • 接著,展開下面的 Link Binary With Libraries點(diǎn)擊加號(hào), 為 IOS 添加 lib$crate_static.a文件。
    Flutter調(diào)用Rust代碼操作指南
    完成后如下圖:
    Flutter調(diào)用Rust代碼操作指南

綁定一開始生成的頭文件bridge_generated.h。

ios/Runner/Runner-Bridging-Header.h 中添加:bridge_generated.h

#import "GeneratedPluginRegistrant.h"
#import "bridge_generated.h"

ios/Runner/AppDelegate.swift 中添加dummy_method_to_enforce_bundling()

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    let dummy = dummy_method_to_enforce_bundling()
    print(dummy)
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

Flutter調(diào)用

至此,配置工作已全部結(jié)束。下面我們看下如何調(diào)用,首先我們簡單封裝一個(gè)方法調(diào)用類。

import 'dart:ffi';
import 'dart:io';

import 'package:flutter_ffi/ffi/rust_ffi.dart';

class NativeFFI {
  NativeFFI._();

  static DynamicLibrary? _dyLib;

  static DynamicLibrary get dyLib {
    if (_dyLib != null) return _dyLib!;

    if (Platform.isIOS) {
      _dyLib = DynamicLibrary.process();
    } else if (Platform.isAndroid) {
      _dyLib = DynamicLibrary.open('librust_demo.so');
    } else {
      throw Exception('DynamicLibrary初始化失敗');
    }

    return _dyLib!;
  }
}

class NativeFun {
  static final _ffi = RustDemoImpl(NativeFFI.dyLib);

  static Future<void> websocketConnect(String host) async {
    return await _ffi.websocketConnect(host: host);
  }

  static Future<void> sendMessage(String host, String message) async {
    return await _ffi.sendMessage(host: host, message: message);
  }

  static Future<void> websocketDisconnect(String host) async {
    return await _ffi.websocketDisconnect(host: host);
  }
}

使用時(shí),直接調(diào)用NativeFun.xxx()方法將可以了。


以上示例代碼我已經(jīng)提交到Github,有需要的可以運(yùn)行查看。對(duì)你有幫助的話,點(diǎn)贊收藏起來~我們下個(gè)月再見!

參考

  • Flutter和Rust如何優(yōu)雅的交互

  • flutter_rust_bridge中文版文檔文章來源地址http://www.zghlxwxcb.cn/news/detail-486517.html

到了這里,關(guān)于Flutter調(diào)用Rust代碼操作指南的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Excel 端口操作指南

    Excel 端口操作指南

    通過將 EDI 報(bào)文可視化為 Excel,企業(yè)可以更好地了解和處理數(shù)據(jù),提高工作效率,減少錯(cuò)誤率。在未實(shí)現(xiàn) EDI 系統(tǒng)和內(nèi)部業(yè)務(wù)系統(tǒng)集成之前,Excel 方案則是一項(xiàng)可供選擇的臨時(shí)替代方案。 Excel方案的優(yōu)點(diǎn)在于,無需對(duì)業(yè)務(wù)系統(tǒng)再做開發(fā)工作,數(shù)據(jù)可讀性較強(qiáng)。用戶只需將交易伙

    2024年02月15日
    瀏覽(22)
  • Linux常規(guī)操作指南

    (1)查看當(dāng)前目錄內(nèi)容 或查看詳細(xì)信息: (2)切換工作目錄 (3)創(chuàng)建新目錄 (4)刪除空目錄 (5)刪除文件或目錄(遞歸刪除) (1)復(fù)制文件或目錄 (2)移動(dòng)或重命名文件/目錄 (3)查看文件內(nèi)容 (4)編輯文件(使用vi/vim編輯器) 在vi中,輸入 i 進(jìn)入插入模式,編輯

    2024年01月19日
    瀏覽(19)
  • Git操作指南

    Git是目前最流行的版本控制系統(tǒng)之一,它為開發(fā)者提供了便捷的代碼管理和協(xié)作工具。對(duì)于初學(xué)者來說,熟悉Git的操作和基本概念是非常重要的。本文將帶你從入門到進(jìn)階,逐步掌握Git的常用操作和技巧。 1、Git簡介: Git是什么?為什么需要使用Git? Git是一個(gè)分布式版本控制

    2024年01月19日
    瀏覽(25)
  • git常用操作指南

    git常用操作指南

    先可以使用git tag命令查看下當(dāng)前有哪些tag,然后在原有tag的基礎(chǔ)上增加版本號(hào),并提交tag信息,例如: 即可 如果有個(gè)項(xiàng)目是用git的lfs管理的,那么首先需要安裝git-lfs 然后執(zhí)行: 最后,git clone 如何刪除本地某個(gè)分支: 在刪除你想刪除的那個(gè)分支前,需要先切換到其他分支,

    2024年02月07日
    瀏覽(22)
  • rabbitMQ入門指南:管理頁面全面指南及實(shí)戰(zhàn)操作

    rabbitMQ入門指南:管理頁面全面指南及實(shí)戰(zhàn)操作

    ??在前一篇文章在centos stream 9環(huán)境中部署和使用rabbitMQ,我們已經(jīng)詳細(xì)介紹了如何在CentOS下安裝和配置RabbitMQ,我們不僅啟動(dòng)了RabbitMQ服務(wù),還通過插件安裝了管理后臺(tái),并且登陸到管理頁面。 ??RabbitMQ管理后臺(tái)提供了一個(gè)直觀的用戶界面,允許我們查看和管理RabbitMQ服務(wù)器

    2024年02月12日
    瀏覽(29)
  • Rocky Linux操作指南

    Rocky Linux操作指南

    rocky Linux 相信還有一些同學(xué)會(huì)比較陌生。好像平常只聽說過Ubuntu和centos。rocky Linux 是個(gè)什么東西呢。它其實(shí)就是centos8的更穩(wěn)定版本:centos8 測(cè)試版 -- rhel8 -- rocky8 它現(xiàn)在已經(jīng)更新到了第九代的一個(gè)版本,我們暫時(shí)先不用那么高的。先用rocky8.6版本熟悉一下基礎(chǔ)的操作。 CentOS

    2024年02月03日
    瀏覽(22)
  • Python 列表操作指南3

    示例,將新列表中的所有值設(shè)置為 \\\'hello\\\': 表達(dá)式還可以包含條件,不像篩選器那樣,而是作為操縱結(jié)果的一種方式: 示例,返回 \\\"orange\\\" 而不是 \\\"banana\\\": 列表對(duì)象具有 sort() 方法,默認(rèn)情況下將對(duì)列表進(jìn)行字母數(shù)字排序,升序排列: 示例,對(duì)列表按字母順序排序: 示例,對(duì)

    2024年02月08日
    瀏覽(14)
  • Python 列表操作指南1

    Python 列表 列表用于在單個(gè)變量中存儲(chǔ)多個(gè)項(xiàng)目。列表是 Python 中的 4 種內(nèi)置數(shù)據(jù)類型之一,用于存儲(chǔ)數(shù)據(jù)集合,其他 3 種分別是元組(Tuple)、集合(Set)和字典(Dictionary),它們具有不同的特性和用途。 使用方括號(hào)創(chuàng)建列表: 列表項(xiàng)是有序的、可變的,并且允許重復(fù)值。

    2024年02月08日
    瀏覽(24)
  • 銀河麒麟服務(wù)器操作系統(tǒng)【進(jìn)入救援模式】操作指南

    銀河麒麟服務(wù)器操作系統(tǒng)【進(jìn)入救援模式】操作指南

    ?銀河麒麟服務(wù)器操作系統(tǒng)使用光驅(qū)或者U盤啟動(dòng)盤引導(dǎo)進(jìn)入救援模式的操作方法類似,這里不再闡述。 以銀河麒麟服務(wù)器操作系統(tǒng)V10使用光驅(qū)或者U盤啟動(dòng)盤進(jìn)入救援模式為例,具體操作步驟如下: 1.插入光驅(qū)或者U盤啟動(dòng)盤后,重啟系統(tǒng),再根據(jù)屏幕下方的提示,按相應(yīng)鍵進(jìn)

    2024年01月21日
    瀏覽(22)
  • Docker 命令和組合操作指南

    Docker 是一種流行的容器化平臺(tái),允許開發(fā)人員在隔離的環(huán)境中構(gòu)建、打包、發(fā)布和運(yùn)行應(yīng)用程序。下面是一些 Docker 的基礎(chǔ)命令: docker version :檢查 Docker 版本信息。 docker info :顯示 Docker 系統(tǒng)信息,如運(yùn)行的容器數(shù)量和鏡像數(shù)量等。 docker search image :搜索 Docker Hub 上的鏡像

    2024年02月12日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包