undefined reference to 'AAssetManager_fromJava'

本文介绍如何在Android JNI开发中使用C++读取assets文件夹内的资源,并提供了一个具体的示例,展示了从Java调用C++方法的过程及C++中读取文件的具体实现。此外,还分享了在使用CMake构建时遇到的问题及其解决方案。

在Android JNI开发时,有时需要在C++文件中读取assets中的文件,通常的做法是通过public native void  readFromAssets(AssetManager ass, String filename);方法实现,网上有很多资料,一般是在Java中定义native方法:

public native void  readFromAssets(AssetManager ass, String filename);

然后再C++中实现

extern "C"
void  Java_ghome_snda_com_ndktest_MainActivity_readFromAssets(JNIEnv* env,jclass tis
        ,jobject assetManager,jstring filename)
{
    AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);
    if(mgr==NULL)
    {
        __android_log_print(ANDROID_LOG_INFO, "zj", ":%s", "AAssetManager==NULL");
        //LOGI(" %s","AAssetManager==NULL");
        return ;
    }

    /*获取文件名并打开*/
    jboolean iscopy;
    const char *mfile = env->GetStringUTFChars(filename, &iscopy);
    AAsset* asset = AAssetManager_open(mgr, mfile,AASSET_MODE_UNKNOWN);
    env->ReleaseStringUTFChars(filename, mfile);
    if(asset==NULL)
    {
       // LOGI(" %s","asset==NULL");
        __android_log_print(ANDROID_LOG_INFO, "zj", ":%s", "asset==NULL");
        return ;
    }
    /*获取文件大小*/
    off_t bufferSize = AAsset_getLength(asset);
    //LOGI("file size         : %d\n",bufferSize);
    __android_log_print(ANDROID_LOG_INFO, "zj", "file size  : %d\\n", bufferSize);
    char *buffer=(char *)malloc(bufferSize+1);
    buffer[bufferSize]=0;
    int numBytesRead = AAsset_read(asset, buffer, bufferSize);
  //  LOGI(": %s",buffer);
    __android_log_print(ANDROID_LOG_INFO, "zj", ": %s\\n", buffer);
    free(buffer);
    /*关闭文件*/
    AAsset_close(asset);
}

我的目录结构:

我所实现的功能是在C++中读取test.txt中的内容。

编译后报错:



解决方法::NDK使用的CmakeList.txt,该错误是由于CMake文件配置错误引起的

只需要在find_library和target_like_libraries中加入Android声明即可:


网上很多针对这个问题的解决方案都说的模棱两可,让人看不明白,现在通过这种方法成功解决。

在嵌入式开发或其他低级系统编程中,当遇到类似 `undefined reference to '_close'` 这样的链接错误时,通常是因为你的程序尝试调用了某些标准库函数(如 `_close`, `_fstat`, `_isatty`, `_lseek`, `_read`),但这些函数未被正确实现或映射到目标平台。 ### 原因分析 这些问题常出现在跨平台开发、裸机环境、操作系统模拟等场景下。例如,在使用 GNU 工具链编译针对特定硬件的目标文件时,默认的标准库可能无法直接支持所有功能。尤其是当你试图将串口作为标准输入/输出设备重定向时: 1. **标准I/O库依赖**:像 `_close`, `_fstat`, 等底层操作符由 C 标准库提供默认实现,但在非 POSIX 兼容环境中(比如单片机或 RTOS),这些函数需要自定义实现。 2. **缺乏移植层**:如果目标平台上缺少对上述系统的实际支持,则必须通过编写 stub 函数来覆盖掉它们的行为,并按照需求定制化处理。 3. **链接阶段问题**:有时也可能由于配置不当导致正确的运行时库未能成功加载进项目构建流程内。 ### 解决方案 #### 一、为缺失的功能添加简单的Stub版本 对于不需要完整功能的情况可以简单返回固定值: ```c int _close(int file) { return -1; } int _fstat(int file, struct stat *st) { st->st_mode = S_IFCHR; return 0; } int _isatty(int file) { return 1;} off_t _lseek(int file, off_t ptr, int dir){return 0;} ssize_t _read(int file,char *ptr,size_t len){ // 实现从串口中读取数据逻辑... return some_serial_read_function(ptr,len); } ``` #### 二、修改Makefile或者IDE设置确保包含适当的Runtime Library 检查并确认是否已经包含了适合当前体系结构的CRT (C Run-Time) 库路径及选项. #### 三、利用专门工具生成所需的weak symbol definitions 一些高级交叉编译器能够自动为我们产生基本的弱符号定义模板,然后用户只需补充必要的部分即可完成整个过程. 以上步骤应该可以帮助解决大部分此类链接失败的问题了!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值