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

Android NDK导入C静态库(.a)出现未定义符号错误求助

解决方案:Android NDK链接C静态库未定义符号问题

核心问题分析

你遇到的链接错误主要来自三个点:

  • CMake未正确导入预编译静态库,错误地将头文件当作库源文件
  • C++调用C函数时未处理名字修饰导致符号不匹配
  • JNI与Kotlin层的参数类型不匹配(单个Byte无法对应C的字节数组指针)

1. 修正CMakeLists配置

你的CMake代码错误地用头文件创建静态库,正确做法是直接导入预编译的librgil.a:

cmake_minimum_required(VERSION 3.22.1)
project(libraryconnector)

# 导入预编译的C静态库
add_library(es_rgil STATIC IMPORTED)
# 配置库路径和头文件目录,根据你的实际文件位置调整
set_target_properties(es_rgil PROPERTIES
    # 假设librgil.a放在src/main/cpp/libs/[ABI]/目录下
    IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/librgil.a
    # 指定头文件所在目录,让编译器能找到es_rgil.h
    INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}
)

# 构建你的JNI共享库
add_library(
        libraryconnector
        SHARED
        native-lib.cpp)

# 链接静态库到你的JNI库
target_link_libraries(
        libraryconnector
        es_rgil)

注意:

  • 要把librgil.a放到对应ABI的子目录,比如src/main/cpp/libs/arm64-v8a/、src/main/cpp/libs/armeabi-v7a/
  • 在Module的build.gradle中指定支持的ABI:
    android {
        defaultConfig {
            ndk {
                abiFilters 'arm64-v8a', 'armeabi-v7a' // 和你的库架构匹配
            }
        }
    }
    

2. 修复C++与C函数的名字修饰问题

因为你的JNI文件是.cpp(C++),调用C编写的库函数时,必须用extern "C"包裹头文件,避免C++名字修饰导致符号找不到:

#include <jni.h>
// 用extern "C"包裹C头文件,确保函数名按C规则解析
extern "C" {
#include "es_rgil.h"
}

extern "C" JNIEXPORT int32_t JNICALL
Java_com_bartosz_lewandowski_libraryconnector_MainActivity_mifareAuth(
        JNIEnv *env,
        jobject /* this */,
        jbyte sector,
        jboolean keyType,
        jbyteArray key, // 改成jbyteArray,对应Kotlin的ByteArray
        jsize len) {

    es_rgil_mifare_key_type k_type = ES_RGIL_MIFARE_KEY_A;
    if (keyType) {
        k_type = ES_RGIL_MIFARE_KEY_B;
    }

    // 将JNI的字节数组转为C指针
    uint8_t* key_ptr = reinterpret_cast<uint8_t*>(env->GetByteArrayElements(key, nullptr));
    if (!key_ptr) return -1; // 处理内存分配失败

    int32_t result = es_rgil_mifare_auth(
        static_cast<uint8_t>(sector), 
        k_type, 
        key_ptr, 
        static_cast<size_t>(len)
    );

    // 释放JNI数组资源
    env->ReleaseByteArrayElements(key, reinterpret_cast<jbyte*>(key_ptr), JNI_ABORT);

    return result;
}

3. 修正Kotlin层函数声明

原来的key: Byte是单个字节,和C函数需要的字节数组指针不匹配,改成ByteArray:

external fun mifareAuth(sector: Byte, isKeyTypeB: Boolean, key: ByteArray, len: Int): Int

额外检查项

  • 确认librgil.a的架构和你编译的ABI完全一致(比如库是arm64-v8a,就不要编译x86)
  • 检查es_rgil.h中是否正确定义了es_rgil_mifare_key_type枚举,确保ES_RGIL_MIFARE_KEY_A/B是有效值
  • 清理项目后重新构建(Build → Clean Project → Rebuild Project)

内容的提问来源于stack exchange,提问作者Bartosz Lewandowski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 10:42:02