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,但未成功,反而报错。
问题原因
find_package(engine REQUIRED CONFIG)不适用,因为你没有为静态库生成对应的CMake配置文件(如engine-config.cmake)- 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
相关产品推荐
相关产品推荐

