4.0 KiB
4.0 KiB
FFI Troubleshooting
UniFFI 版本
本项目使用 UniFFI 0.31,采用 UDL + proc-macro 混合模式:
- UDL(
zx_document.udl):定义类型和函数签名 #[uniffi::export]proc-macro:生成 C ABI 分发符号uniffi-bindgen:生成 Swift/Kotlin 绑定代码
常见问题
No such module 'ZxDocumentRuntime'
原因:XCFramework 未正确添加到 Xcode 项目。
解决:
- 确认
bindings/ios/ZxDocumentRuntime.xcframework已生成 - 在 Xcode → Target → General → Frameworks 中添加
- 确保 Embed 设置为
Do Not Embed(静态库)
Undefined symbol: _ffi_zx_document_ffi_*
原因:C ABI 符号未导出。proc-macro 生成的符号名称可能与链接器期望不一致。
解决:
- 确认
crates/zx_document_ffi/src/lib.rs中#[no_mangle] pub extern "C"函数存在 - 检查 Cargo.toml
crate-type = ["lib", "staticlib", "cdylib"] - 运行
nm target/aarch64-apple-ios/release/libzx_document_ffi.a | grep ffi_验证符号 - 确认 UDL 中声明的函数与
#[uniffi::export]函数名称一致
Library not found for -lzx_document_ffi
原因:Library Search Paths 未设置。
解决:
- Build Settings → Library Search Paths → 添加
$(PROJECT_DIR)/bindings/ios - 或使用绝对路径指向
.xcframework所在目录
UniFFI checksum mismatch
原因:UDL 文件更新后未重新生成 Swift binding。
解决:
uniffi-bindgen generate \
--language swift \
--out-dir bindings/ios/generated \
crates/zx_document_ffi/src/zx_document.udl
setup_scaffolding!() not called
原因:uniffi::setup_scaffolding!() 必须在 lib.rs 的第一行调用。
解决:确认 crates/zx_document_core/src/lib.rs 第一行是 uniffi::setup_scaffolding!();
新增类型/函数后 Swift 不可见
原因:只在 Rust 侧添加了类型/函数,但未更新:
- UDL 文件声明
- FFI crate
pub use重导出 - Swift binding 重新生成
完整的 FFI 接入步骤:
# 1. Rust 侧添加类型 + 函数 + UDL 声明
# 2. FFI crate: pub use 重导出 + #[uniffi::export] 包装
# 3. 重新生成 Swift
uniffi-bindgen generate --language swift \
--out-dir bindings/ios/generated \
crates/zx_document_ffi/src/zx_document.udl
# 4. 验证编译
cargo build --release --target aarch64-apple-ios -p zx_document_ffi
cargo build 目标平台不匹配
原因:macOS 上构建 iOS 目标需要 Apple Silicon target。
解决:
rustup target add aarch64-apple-ios aarch64-apple-ios-sim
infer / comrak / zip crate 编译失败
原因:某些 crate 在 iOS target 下有 C 依赖。
解决:
comrak:需要启用--features中的onig或使用syntect后端zip:纯 Rust,无特殊要求- 确保
CC环境变量指向 Xcode toolchain
XCFramework 构建注意事项
- 必须分别编译 device 和 simulator 目标
lipo不需要(两个 .a 文件各自是 fat binary)- header 文件由
uniffi-bindgen生成:bindings/ios/generated/zx_documentFFI.h - modulemap 文件创建:
framework module ZxDocumentRuntime {
header "zx_documentFFI.h"
export *
}
UDL 类型不支持
问题类型:
Vec<(String, &str)>— 不支持 tuple- 泛型函数 — 不支持
- 生命周期参数 — 不支持
解决:在 FFI 层创建包装类型。例如 search_pdf_text(&[(u32, &str)]) → FFI 包装为 search_pdf_pages(Vec<u32>, Vec<String>)。
Rust 与 iOS 持有引用
UniFFI 生成的对象是 值类型(序列化跨 FFI 边界传递),不是引用类型。Rust 侧的 Mutex 保护全局状态,iOS 侧通过函数调用读写状态。
验证清单
cargo build --release --target aarch64-apple-ios通过cargo build --release --target aarch64-apple-ios-sim通过nm验证 C ABI 符号存在- Swift binding 生成并编译通过
- XCFramework 包含 device + simulator slices
- header + modulemap 正确
- demo App 链接成功