flutter 调用c++,rust

简介: flutter 调用c++,rust
环境

Python 3.11.0

rustc 1.68.0 (2c8cc3432 2023-03-06)

Mac

调用流程

c++或rust

anoidrd生成so文件, ios生成.a文件

通过ffi间接调用

flutter 调用.cpp
native_lib.cpp
#include <stdint.h>
#include <cstring>
extern "C" {
    __attribute__((visibility("default"))) __attribute__((used))
    int32_t native_add(int32_t x, int32_t y) {
        return x + y;
    }
     __attribute__((visibility("default"))) __attribute__((used))
    int32_t native_add2(int32_t x, int32_t y) {
            return x + y;
    }
     __attribute__((visibility("default"))) __attribute__((used))
    char* concat(const char* str1, const char* str2) {
        int len1 = strlen(str1);
        int len2 = strlen(str2);
        char* result = new char[len1 + len2 + 1];
        strcpy(result, str1);
        strcat(result, str2);
        return result;
    }
}


extern "C" __attribute__((visibility("default"))) __attribute__((used))
int32_t native_add3(int32_t x, int32_t y) {
        return x + y;
 }

新建android\CMakeLists.txt
 cmake_minimum_required(VERSION 3.18.1) # for example
 add_library(native_lib
        # Sets the library as a shared library.
        SHARED
        # Provides a relative path to your source file(s).
        ../ios/Runner/native_lib.cpp )
app/build.gradle
    externalNativeBuild {
        // Encapsulates your CMake build configurations.
        cmake {
            // Provides a relative path to your CMake build script.
            path "../CMakeLists.txt"
        }
    }
local.properties

ndk.dir=C:\sdk\androidsdk\Android\Sdk\ndk\24.0.8215888

native_add.dart
import 'dart:ffi' as ffi;
import 'dart:ffi';
import 'dart:io'; // For Platform.isX

import 'package:ffi/ffi.dart';

final DynamicLibrary nativeAddLib = Platform.isAndroid
    ? DynamicLibrary.open("libnative_lib.so")
    : DynamicLibrary.process();


final int Function(int x, int y) nativeAdd = nativeAddLib
    .lookup<NativeFunction<Int32 Function(Int32, Int32)>>("native_add")
    .asFunction();


final int Function(int x, int y) nativeAdd2 = nativeAddLib
    .lookup<NativeFunction<Int32 Function(Int32, Int32)>>("native_add2")
    .asFunction();

final int Function(int x, int y) nativeAdd3 = nativeAddLib
    .lookup<NativeFunction<Int32 Function(Int32, Int32)>>("native_add3")
    .asFunction();

typedef A2 = Pointer<Utf8> Function(ffi.Pointer<Utf8>, ffi.Pointer<Utf8>);

String concatStr(String str1, String str2) {
  final privateKeyPtr = str1.toNativeUtf8();
  final hexCidMessagePtr = str2.toNativeUtf8();
  final concat =
      nativeAddLib.lookup<ffi.NativeFunction<A2>>('concat').asFunction<A2>();
  return concat(privateKeyPtr, hexCidMessagePtr).toDartString();
}


bool isExistSymbol(String symbol) {
  final isOk = nativeAddLib.providesSymbol(symbol);
  return isOk;
}

flutter 调用rust
创建 flutter项目或者插件
添加依赖

flutter_rust_bridge: ^1.71.0

ffi: ^2.0.1

ffigen: ^7.2.8

在根目录下创建rust项目

cargo new --lib native

拷贝api.rs,lib.rs

//lib.rs
mod api;
mod bridge_generated;

//api.ts
// This is the entry point of your Rust library.
// When adding new code to your project, note that only items used
// here will be transformed to their Dart equivalents.

// A plain enum without any fields. This is similar to Dart- or C-style enums.
// flutter_rust_bridge is capable of generating code for enums with fields
// (@freezed classes in Dart and tagged unions in C).
pub enum Platform {
    Unknown,
    Android,
    Ios,
    Windows,
    Unix,
    MacIntel,
    MacApple,
    Wasm,
}

// A function definition in Rust. Similar to Dart, the return type must always be named
// and is never inferred.
pub fn platform() -> Platform {
    // This is a macro, a special expression that expands into code. In Rust, all macros
    // end with an exclamation mark and can be invoked with all kinds of brackets (parentheses,
    // brackets and curly braces). However, certain conventions exist, for example the
    // vector macro is almost always invoked as vec![..].
    //
    // The cfg!() macro returns a boolean value based on the current compiler configuration.
    // When attached to expressions (#[cfg(..)] form), they show or hide the expression at compile time.
    // Here, however, they evaluate to runtime values, which may or may not be optimized out
    // by the compiler. A variety of configurations are demonstrated here which cover most of
    // the modern oeprating systems. Try running the Flutter application on different machines
    // and see if it matches your expected OS.
    //
    // Furthermore, in Rust, the last expression in a function is the return value and does
    // not have the trailing semicolon. This entire if-else chain forms a single expression.
    if cfg!(windows) {
        Platform::Windows
    } else if cfg!(target_os = "android") {
        Platform::Android
    } else if cfg!(target_os = "ios") {
        Platform::Ios
    } else if cfg!(all(target_os = "macos", target_arch = "aarch64")) {
        Platform::MacApple
    } else if cfg!(target_os = "macos") {
        Platform::MacIntel
    } else if cfg!(target_family = "wasm") {
        Platform::Wasm
    } else if cfg!(unix) {
        Platform::Unix
    } else {
        Platform::Unknown
    }
}

// The convention for Rust identifiers is the snake_case,
// and they are automatically converted to camelCase on the Dart side.
pub fn rust_release_mode() -> bool {
    cfg!(not(debug_assertions))
}

pub fn test() -> String {
    String::from("这是一个rust函数")
}

配置

Cargo.toml

[package]
name = "native"
version = "0.1.0"
edition = "2021"

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

[build-dependencies]
flutter_rust_bridge_codegen = "=1.71.0"

[dependencies]
flutter_rust_bridge = "=1.71.0"
flutter_rust_bridge_macros = "=1.71.0"


添加run_gen.sh
flutter_rust_bridge_codegen \
        --rust-input native/src/api.rs \
        --dart-output lib/bridge_generated.dart \
        --c-output ios/Classes/bridge_generated.h
其他命令

cargo install flutter_rust_bridge_codegen

android相关

cargo install cargo-ndk

rustup target add aarch64-linux-android

rustup target add armv7-linux-androideabi

rustup target add x86_64-linux-android

rustup target add i686-linux-android

ios相关

64 bit targets (真机 & 模拟器):

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

New simulator target for Xcode 12 and later

ustup target add aarch64-apple-ios-sim

gradle.properties app/build.gradle

ANDROID_NDK=/Users/yujunlong/Library/Android/sdk/ndk/24.0.8215888


[
        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',
                '-t', 'x86',
                '-t', 'x86_64',
                '-o', '../android/app/src/main/jniLibs', 'build'
        if (profileMode != null) {
            args profileMode
        }
    }
}
ios 配置

在native(rust项目下面)下面执行

cargo xcode

在 Xcode 中打开 ios/Runner.xcodeproj

xcode中选中Runner 然后File —> Add Files to “Runner”

native.xcodeproj

点击 Runner 根项目,TARGETS —> Build Phases —> Target Dependencies :请添加 native-staticlib

展开 Link Binary With Libraries:添加 libnative_static.a

Runner-Bridging-Header.h
#import "GeneratedPluginRegistrant.h"
#import "bridge_generated.h"

AppDelegate.swift 添加

print(“dummy_value=(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 {
     print("dummy_value=\(dummy_method_to_enforce_bundling())");
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application,       didFinishLaunchingWithOptions: launchOptions)
  }
}

相关文章
|
2月前
|
Rust 安全 程序员
Rust与C++:内存管理与安全性的比较
本文将对Rust和C++两种编程语言在内存管理和安全性方面进行深入比较。我们将探讨Rust如何通过其独特的所有权系统和生命周期管理来消除内存泄漏和悬挂指针等常见问题,并对比C++在这方面的挑战。此外,我们还将讨论Rust的类型系统和编译器如何在编译时捕获许多常见的运行时错误,从而提高代码的安全性。
|
2月前
|
Web App开发 Rust 安全
一名C++程序员的Rust入门初体验
作者最近尝试写了一些Rust代码,本文主要讲述了对Rust的看法和Rust与C++的一些区别。
158 3
|
2月前
|
Rust 算法 C++
【从 C++ 到 Rust:掌握 Rust 基础语法】From C++ to Rust: Mastering Rust Basics
【从 C++ 到 Rust:掌握 Rust 基础语法】From C++ to Rust: Mastering Rust Basics
68 0
|
11月前
|
Rust 自然语言处理 Java
单链表的多语言表达:C++、Java、Python、Go、Rust
单链表是一种链式数据结构,由一个头节点和一些指向下一个节点的指针组成。每个节点包含一个数据元素和指向下一个节点的指针。头节点没有数据,只用于表示链表的开始位置。单链表相对于数组的优点是插入和删除元素时不需要移动其他元素,时间复杂度为O(1)。但是,在查找元素时,单链表比数组要慢,时间复杂度为O(n)。
16644 7
|
开发框架 Rust .NET
TechEmpower 21 轮 Web 框架性能评测 -- C# 的性能和 Rust、C++ 并驾齐驱
版权声明:本文为 CSDN 博主「shanyou」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/shanyou/article/details/126081288
1489 1
|
存储 Rust 测试技术
用Python绑定调用C/C++/Rust库
Python绑定可以让Python程序调用C/C++/Rust编译的库函数,从而让我们在不重复造轮子的前提下,兼具Python和C/C++二者的优点。
243 0
用Python绑定调用C/C++/Rust库
|
机器学习/深度学习 Rust 安全
华为OD 2023机试题java python c++ go rust
华为OD 2023机试题java python c++ go rust
211 0
华为OD  2023机试题java python c++ go  rust
|
存储 机器学习/深度学习 Rust
厌倦了C++,CS&ML博士用Rust重写Python扩展,还总结了9条规则
厌倦了C++,CS&ML博士用Rust重写Python扩展,还总结了9条规则
152 0
|
Rust 数据可视化 安全
【番外篇】Rust环境搭建+基础开发入门+Rust与.NET6、C++的基础运算性能比较
突然想打算把Rust作为将来自己主要的副编程语言。当然,主语言还是C#,毕竟.NET平台这么强大,写起来就是爽。缘起:之前打算一些新的产品或者新的要开发的东西,由于没有历史包袱,就想重新选型一下,在.NET平台(C#语言)、Golang、Rust里面进行选择一个。
265 0
【番外篇】Rust环境搭建+基础开发入门+Rust与.NET6、C++的基础运算性能比较
|
4天前
|
编译器 C++
【C++】string类的使用④(字符串操作String operations )
这篇博客探讨了C++ STL中`std::string`的几个关键操作,如`c_str()`和`data()`,它们分别返回指向字符串的const char*指针,前者保证以&#39;\0&#39;结尾,后者不保证。`get_allocator()`返回内存分配器,通常不直接使用。`copy()`函数用于将字符串部分复制到字符数组,不添加&#39;\0&#39;。`find()`和`rfind()`用于向前和向后搜索子串或字符。`npos`是string类中的一个常量,表示找不到匹配项时的返回值。博客通过实例展示了这些函数的用法。