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

Android平台从C++调用Rust静态库时出现未定义符号错误

解决Android调用Rust静态库时的未定义符号错误

问题重现

我有一个编译为Android静态库(engine.a)的Rust库,其中包含C兼容的FFI函数。已实现Java绑定调用,现在希望直接从C++调用这些函数(无需JNI)。

编译后将静态库放在PROJECT_ROOT/android/jniLibs目录(Android默认自动打包路径),结构如下:

android
  - jniLibs
    - arm64-v8a
       - engine.a
    - armeabi-v7a
       - engine.a
... // 其他支持架构

用cbindgen生成了包含C兼容函数的头文件engine.h,所有函数都已添加no_mangle和extern "C"注解,与C++源码放在一起。该方案在iOS上正常运行,但Android编译时出现未定义符号错误。

Android Studio中导入头文件无报错,调用代码示例:

#include "engine.h"

...

int res = my_rust_fn();

当前CMakeLists.txt配置:

add_library(
        ${PACKAGE_NAME}
        SHARED
    ../cpp/bindings.cpp # 调用engine.h函数的C++文件
    ../cpp/engine.h
    cpp-adapter.cpp
)

include_directories(
    ../cpp
)

set_target_properties(
  ${PACKAGE_NAME} PROPERTIES
  CXX_STANDARD 17
  CXX_EXTENSIONS OFF
  POSITION_INDEPENDENT_CODE ON
)

find_package(ReactAndroid REQUIRED CONFIG)
find_package(fbjni REQUIRED CONFIG)


target_link_libraries(
  ${PACKAGE_NAME}
  fbjni::fbjni
  ReactAndroid::jsi
  ReactAndroid::turbomodulejsijni
  ReactAndroid::react_nativemodule_core
  android
)

编译错误信息:

ld: error: undefined symbol: my_rust_fn
>>> referenced by bindings.cpp:91

尝试用find_package(engine REQUIRED CONFIG)并在链接时添加engine,但未成功,反而报错。

问题原因

  1. find_package(engine REQUIRED CONFIG)不适用,因为你没有为静态库生成对应的CMake配置文件(如engine-config.cmake)
  2. Android的jniLibs目录是给Java层自动打包用的,CMake默认不会自动扫描该目录下的静态库

解决方案

修改CMakeLists.txt,手动指定静态库的路径并完成链接:

步骤1:定义静态库路径

利用CMake的ANDROID_ABI变量自动匹配当前编译的架构,定位对应的engine.a:

# 定位对应架构的engine.a路径
set(ENGINE_LIB_DIR "${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}")
set(ENGINE_LIB "${ENGINE_LIB_DIR}/engine.a")

步骤2:检查静态库是否存在

添加文件存在性检查,避免编译时因找不到库而失败:

if(NOT EXISTS ${ENGINE_LIB})
    message(FATAL_ERROR "找不到对应架构的engine.a:${ENGINE_LIB}")
endif()

步骤3:链接静态库

在target_link_libraries中添加静态库文件:

target_link_libraries(
  ${PACKAGE_NAME}
  # 加入Rust静态库
  ${ENGINE_LIB}
  fbjni::fbjni
  ReactAndroid::jsi
  ReactAndroid::turbomodulejsijni
  ReactAndroid::react_nativemodule_core
  android
)

修改后的完整CMakeLists.txt片段

add_library(
        ${PACKAGE_NAME}
        SHARED
    ../cpp/bindings.cpp
    ../cpp/engine.h
    cpp-adapter.cpp
)

include_directories(
    ../cpp
)

# 新增:配置Rust静态库路径
set(ENGINE_LIB_DIR "${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}")
set(ENGINE_LIB "${ENGINE_LIB_DIR}/engine.a")

if(NOT EXISTS ${ENGINE_LIB})
    message(FATAL_ERROR "找不到对应架构的engine.a:${ENGINE_LIB}")
endif()

set_target_properties(
  ${PACKAGE_NAME} PROPERTIES
  CXX_STANDARD 17
  CXX_EXTENSIONS OFF
  POSITION_INDEPENDENT_CODE ON
)

find_package(ReactAndroid REQUIRED CONFIG)
find_package(fbjni REQUIRED CONFIG)

target_link_libraries(
  ${PACKAGE_NAME}
  ${ENGINE_LIB}
  fbjni::fbjni
  ReactAndroid::jsi
  ReactAndroid::turbomodulejsijni
  ReactAndroid::react_nativemodule_core
  android
)

额外检查点

  • 确认Rust编译静态库时,针对每个Android架构都开启了位置无关代码(PIC):在Cargo.toml的[profile.release]块中添加codegen-units = 1,并通过cargo build --target <对应安卓架构> --release编译
  • 确认engine.h中的函数签名与Rust代码extern "C"块中的签名完全一致,包括参数类型、返回值类型,且所有函数都添加了#[no_mangle]属性

内容的提问来源于stack exchange,提问作者Oscar Franco

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 12:04:54