ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

如何用 [manganis::ffi] 在 Dioxus 中集成 Swift/Kotlin 原生插件

如何用 [manganis::ffi] 在 Dioxus 中集成 Swift/Kotlin 原生插件 如何用 #[manganis::ffi] 在 Dioxus 中集成 Swift/Kotlin 原生插件【免费下载链接】dioxusFullstack app framework for web, desktop, and mobile.项目地址: https://gitcode.com/GitHub_Trending/di/dioxus如果你的 Dioxus 应用需要调用只在移动端存在的系统能力比如原生权限弹窗、定位服务直接写build.rs处理 Swift/Kotlin 源码会很繁琐。manganisDioxus 的资产打包工具提供了#[ffi]属性宏你在 Rust 里用extern Swift/extern Kotlin块声明原生接口宏把源码目录作为资产提交给链接器dx打包器在 rustc 之后提取这些元数据自动编译并链接原生代码进最终应用。本文以仓库中的 geolocation-native-plugin 示例为主路径演示如何声明绑定、组织原生源码、配置权限并验证结果。前提条件已安装 Rust 工具链与 Dioxus CLIdx。示例文档中的运行命令依赖dx serve。在 Android/iOS 上构建时需要安装对应的原生工具链Android SDK/NDK、Xcode这样示例的build.rs才能构建原生模块。UI 本身也能在 desktop/web 上运行但定位调用会返回错误错误会在界面内联显示。项目依赖dioxus与manganis。示例的 Cargo.toml 使用 workspace 依赖并声明了三个平台 featuredefault [mobile]、web [dioxus/web]、desktop [dioxus/desktop]、mobile [dioxus/mobile]按需启用。声明 FFI 绑定宏由 manganis 直接导出manganis库内部pub use manganis_macro::ffi;用法是在一个 extern 块上标注#[manganis::ffi(源码目录路径)]路径相对于包根目录。示例 src/plugin/mod.rs 中按平台分别声明/// iOS/macOS 原生绑定路径指向 SwiftPM 包包含 GeolocationPlugin.swift #[cfg(any(target_os ios, target_os macos))] #[manganis::ffi(src/ios/plugin)] unsafe extern Swift { /// 原生 GeolocationPlugin 类 pub type GeolocationPlugin; /// Swift 签名: func getCurrentPositionJson(_ optionsJson: String) - String pub fn getCurrentPositionJson(this: GeolocationPlugin, optionsJson: String) - String; /// Swift 签名: func checkPermissionsJson() - String pub fn checkPermissionsJson(this: GeolocationPlugin) - String; /// Swift 签名: func requestPermissionsJson(_ permissionsJson: String) - String pub fn requestPermissionsJson(this: GeolocationPlugin, permissionsJson: String) - String; } /// Android 原生绑定路径指向 Gradle 工程包含 GeolocationPlugin.kt #[cfg(target_os android)] #[manganis::ffi(src/android)] unsafe extern Kotlin { pub type GeolocationPlugin; /// Kotlin 签名: fun getCurrentPositionJson(optionsJson: String): String pub fn getCurrentPositionJson(this: GeolocationPlugin, optionsJson: String) - String; pub fn checkPermissionsJson(this: GeolocationPlugin) - String; pub fn requestPermissionsJson(this: GeolocationPlugin, permissionsJson: String) - String; }以上为示例代码节选示例中还包含 iOS Live Activity 相关的若干函数。声明时注意每个绑定块只写一个平台的 ABI。宏当前支持SwiftiOS/macOS与KotlinAndroid两种见 manganis-macro 的 ffi 实现。用pub type 名称;声明原生类然后用名称作为方法的this参数来调用实例方法。参数与返回值必须是可跨语言转换的类型bool、i8/i16/i32/i64、u8/u16/u32/u64、f32/f64、String、str、OptionT、ResultT, E、单元类型以及对pub type声明的引用。函数名和参数名要与原生侧的方法一一对应。示例采用的约定是复杂数据序列化为 JSON 字符串传输原生方法以Json后缀命名如getCurrentPositionJson。组织原生源码路径参数直接指向原生源码的工程目录不需要你手动编译或拷贝产物Androidsrc/android是一个 Gradle 工程核心是 GeolocationPlugin.kt 中的class GeolocationPlugin(private val activity: Activity)类名与 Rust 侧的pub type GeolocationPlugin对应并配有AndroidManifest.xml。iOSsrc/ios/plugin是一个 SwiftPM 包含Package.swift核心是 GeolocationPlugin.swiftRust 侧注释里写明了每个函数对应的 Swift 签名。示例 README 说明这些原生 Gradle/Swift 产物通过 linker symbols 嵌入并由dx自动打包你不需要在 Rust 代码里处理原生编译命令。对于不支持的平台web、Linux desktop 等示例提供了一个 fallback 模块让代码能编译通过并在调用时返回明确错误#[cfg(not(any( all(any(target_os ios, target_os macos)), all(target_os android) )))] mod fallback { pub struct GeolocationPlugin; impl GeolocationPlugin { pub fn new() - ResultSelf { Err(Error::PlatformBridge( Geolocation is only supported on Android, iOS, and macOS.to_string(), )) } } // 各 FFI 函数同样返回 PlatformBridge 错误…… }配置权限示例把权限声明放在 Dioxus.toml 的统一 manifest 中而不是手写平台清单[permissions] location { precision fine, description Access your precise location to provide location-based services }CLI 会自动把这些权限映射到平台标识符Android 对应AndroidManifest.xml中的ACCESS_FINE_LOCATIONiOS 对应Info.plist中的NSLocationWhenInUseUsageDescription该说明见示例mod.rs中的注释。同一个 Dioxus.toml 中还配置了构建参数供参考[android] min_sdk 24 target_sdk 34 features [android.hardware.location.gps] [ios] deployment_target 16.2 background_modes [location]在 Dioxus 组件中调用示例用一个Geolocation结构体包装生成的绑定负责 JSON 序列化/反序列化与错误检查原生返回的 JSON 中带error键时转为Err组件侧只面向 Rust 类型编程let on_fetch_position move |_| { let maximum_age max_age_input.read().trim().parse::u32().unwrap_or(0); let options PositionOptions { enable_high_accuracy: use_high_accuracy(), timeout: 10_000, maximum_age, }; match geolocation.write().get_current_position(Some(options)) { Ok(position) { last_position.set(Some(position)); error.set(None); } Err(err) error.set(Some(err.to_string())), } };错误会写入 signal 并在 UI 顶部以 banner 显示成功则更新坐标网格。完整组件逻辑见 src/main.rs。构建与验证在仓库根目录运行示例命令来自示例 READMEdx serve --project examples/01-app-demos/geolocation --platform mobile注意README 中写的项目路径是examples/01-app-demos/geolocation而该示例在当前仓库中的实际目录名为geolocation-native-plugin如果你的路径与 README 不一致请以实际目录为准替换。验证方式README 的 Things to try点Check permissions查看当前系统状态granted/denied/prompt。点Request permissions触发原生权限弹窗。切换High accuracy、设置Max cached age再请求当前位置。观察坐标网格是否随新读数更新失败时如权限被拒或在非移动端运行会显示错误 banner例如 Geolocation is only supported on Android, iOS, and macOS。限制与边界宏目前只支持 Swift 与 Kotlin 两种 ABI设计文档中列出的 C 编译等扩展属于计划中的内容见 11-NATIVE-PLUGIN-FFI.md其中 bundler 侧的编译、缓存等条目仍是待办清单。设计文档明确了一个权衡Rust 无法使用原生编译的输出如生成的头文件因为原生代码在 rustc 之后才由打包器编译对于通过 JNI/ObjC 的运行时 FFI 场景没有影响。数据交换依赖你自行约定的序列化方式示例统一用 JSON 字符串Option/Result之外的复杂结构需要在原生侧与 Rust 侧各自定义对应的 JSON 模型示例中的 models.rs 使用 serde 派生。【免费下载链接】dioxusFullstack app framework for web, desktop, and mobile.项目地址: https://gitcode.com/GitHub_Trending/di/dioxus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表