You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

已完成的操作

  1. 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);
}
  1. 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"
        }
    }
  1. 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)
  1. 项目文件结构:
lib/
   - add.cpp
   - add.o
   - CMakeLists.txt
   - libadd.dylib
   - main.dart
  1. 编译dylib的命令:
g++ -c add.cpp
ar rvs libadd.dylib add.o
  1. add.cpp代码:
#define EXPORT extern "C" __attribute__((visibility("default")))
__attribute__((used))

EXPORT
int add(int a, int b){
    return a + b;
}

问题原因分析

  1. 平台库格式不匹配:.dylib是macOS专属的动态库格式,Android基于Linux内核,只能识别.so格式的共享库,你用macOS的g++编译出的dylib完全无法在Android上运行,这是核心问题。
  2. 编译命令错误:用ar rvs生成动态库是错误的,ar是用来创建静态库的工具,生成动态库应该使用g++的-shared参数,而非ar命令。
  3. 库路径与加载逻辑错误:Android应用的动态库必须放在特定ABI目录(如app/src/main/jniLibs/arm64-v8a/),编译后会被打包到APK对应路径;而你用Directory.current.path获取的路径,在Android环境下并非库的正确存放位置。
  4. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 03:31:12