Dart FFI在Android无法加载动态库的问题求助
问题:Android上通过Dart FFI调用libadd.dylib失败,报错找不到库
实现加法功能的C++函数编译为libadd.dylib后,在Android设备上用Dart FFI调用时,始终报错:
Another exception was thrown: Invalid argument(s): Failed to load dynamic library 'libadd.dylib': dlopen failed: library "libadd.dylib" not found
已完成的操作
- Dart实现代码:
import 'dart:ffi' as ffi; import 'dart:io' show Platform, Directory; import 'package:path/path.dart' as path; typedef C_ADD = ffi.Int Function( ffi.Int a, ffi.Int b); // FFI signature of C function typedef ADD = int Function(int a, int b); void linkAndCallFunction() { var libraryPath = path.join(Directory.current.path, "libadd.dylib"); final dylib = ffi.DynamicLibrary.open(libraryPath); final ADD add = dylib.lookup<ffi.NativeFunction<C_ADD>>("add").asFunction(); final result = add(40, 2); print(result); }
- build.gradle中NDK配置
根目录build.gradle:
buildscript{ ext{ ndkVersion = "25.1.8937393" } ...
app/build.gradle:
android { ndkVersion rootProject.ext.ndkVersion externalNativeBuild { cmake { path "../../lib/CMakeLists.txt" } }
- CMakeLists.txt内容:
cmake_minimum_required(VERSION 3.10.2) project(add LANGUAGES CXX C) set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") add_library(add SHARED ./add.cpp)
- 项目文件结构:
lib/ - add.cpp - add.o - CMakeLists.txt - libadd.dylib - main.dart
- 编译dylib的命令:
g++ -c add.cpp ar rvs libadd.dylib add.o
- add.cpp代码:
#define EXPORT extern "C" __attribute__((visibility("default"))) __attribute__((used)) EXPORT int add(int a, int b){ return a + b; }
问题原因分析
- 平台库格式不匹配:
.dylib是macOS专属的动态库格式,Android基于Linux内核,只能识别.so格式的共享库,你用macOS的g++编译出的dylib完全无法在Android上运行,这是核心问题。 - 编译命令错误:用
ar rvs生成动态库是错误的,ar是用来创建静态库的工具,生成动态库应该使用g++的-shared参数,而非ar命令。 - 库路径与加载逻辑错误:Android应用的动态库必须放在特定ABI目录(如
app/src/main/jniLibs/arm64-v8a/),编译后会被打包到APK对应路径;而你用Directory.current.path获取的路径,在Android环境下并非库的正确存放位置。 - CMake配置未生效:你虽然配置了NDK和CMake,但实际并未用它编译Android平台的库,而是手动编译了macOS的dylib,导致配置完全没有发挥作用。
解决方案
1. 用NDK编译Android专属的.so库
放弃手动编译dylib,利用已配置的CMake和NDK生成符合Android要求的共享库:
- 调整CMakeLists.txt(确保语法正确):
cmake_minimum_required(VERSION 3.10.2) project(add LANGUAGES CXX) add_library( add SHARED add.cpp )
- 同步Android Studio项目,执行编译,NDK会自动为不同ABI(如arm64-v8a、armeabi-v7a)生成
libadd.so,存放在app/build/intermediates/cmake/debug/obj/对应ABI目录下。
2. 修正Dart FFI的库加载逻辑
Android运行时会自动识别APK中的.so库路径,无需手动拼接路径,修改Dart代码:
import 'dart:ffi' as ffi; import 'dart:io' show Platform; typedef C_ADD = ffi.Int32 Function(ffi.Int32 a, ffi.Int32 b); typedef ADD = int Function(int a, int b); void linkAndCallFunction() { late ffi.DynamicLibrary dylib; if (Platform.isAndroid) { // Android直接加载库名,系统自动匹配对应ABI的库 dylib = ffi.DynamicLibrary.open("libadd.so"); } else if (Platform.isMacOS) { // macOS测试时加载dylib dylib = ffi.DynamicLibrary.open("libadd.dylib"); } else { throw UnsupportedError("Unsupported platform"); } final ADD add = dylib.lookup<ffi.NativeFunction<C_ADD>>("add").asFunction(); final result = add(40, 2); print(result); }
注意:使用精确的类型(如ffi.Int32)替代模糊的ffi.Int,避免平台差异导致的签名不匹配。
3. 清理无效产物
删除手动生成的add.o、libadd.dylib,避免混淆编译流程。
内容的提问来源于stack exchange,提问作者zh24
相关产品推荐
相关产品推荐

