美文网首页
android平台C++代码约定

android平台C++代码约定

作者: uriah | 来源:发表于2017-07-01 15:44 被阅读0次

    android不同于PC端,android标准输出(stdout)、标准错误(stderr)都被重定向到了/dev/null,printf ,std::cout函数根本不起作用。
    android一般情况下,文件被放进assets目录下,该目录下所有的文件都会被打包至apk中。故model文件应放在此目录下。而放在该处的文件不能通过标准文件IO访问(没有正确的路径)。

    约定1 使用封装的Log代码,而不是cout,printf。

    Logging.h是封装后的代码,在CMakeLists指定编译宏SHOWLOG即可开启日志打印。若未定义宏SHOWLOG则日志不打印。

    Logging.h

    #pragma once
    
    #ifdef __ANDROID__
    #include <android/log.h>
    #else
    #include <iostream>
    #include <stdio.h>
    #endif
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    #ifdef SHOWLOG
    #ifdef __ANDROID__
    #define LOGI(TAG,...)    __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__);
    #define LOGW(TAG,...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__);
    #define LOGE(TAG,...)  __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__);
    #define LOGD(TAG,...)  __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__);
    
    #else
    #define LOGI(TAG,...) \
         do { \
                 std::cout<<__FILE__<<" "<<__LINE__<<"line"<<" "<<TAG<<":  "; \
                 printf(__VA_ARGS__); } \
         while (0)
    
    #define LOGW(TAG,...) \
         do {  \
                 std::cout<<__FILE__<<" "<<__LINE__<<"line"<<" "<<TAG<<":  "; \
                 printf(__VA_ARGS__); } \
         while (0)
    
    #define LOGE(TAG,...) \
         do {  \
           std::cout<<__FILE__<<" "<<__LINE__<<"line"<<" "<<TAG<<":  "; \
           printf(__VA_ARGS__); } \
         while (0)
    #define LOGD(TAG,...) \
         do {  \
           std::cout<<__FILE__<<" "<<__LINE__<<"line"<<" "<<TAG<<":  "; \
           printf(__VA_ARGS__); } \
         while (0)
    #endif
    
    #else
    #define LOGI(TAG,...)
    #define LOGW(TAG,...)
    #define LOGE(TAG,...)
    #define LOGD(TAG,...)
    #endif
    
    #ifdef __cplusplus
    } /* extern "C" */
    #endif
    

    当需要打印日志时,类似于printfLOGD,LOGI,LOGW,LOGE有不同的日志等级

    LOGD("TAG","log = %d",var1);
    

    约定2 库代码尽量不直接从文件读取model,jni层把model读至内存,把内存地址以及长度传给sdk.

    androidassets目录是无法通过文件地址访问的。android提供了<android/asset_manager_jni.h>来访问assets目录。为了避免model的多次copy,建议在jni层把model读至内存,前提是底层c++代码提供相关接口。

    jni层代码

    AAssetManager * manager = AAssetManager_fromJava(env,assetManager);//assetManager是java层对象
    assert(NULL != manager);
    std::string fileName = "model.zip";   //model名称
    AAsset * asset = AAssetManager_open(manager, fileName.c_str(), AASSET_MODE_BUFFER);
    assert(NULL != asset);
    int size = AAsset_getLength(asset);
    const char * buffer = static_cast<const char *>(AAsset_getBuffer(asset));
    

    接口定义类似

    void readModel(const char * buff, int bufLen);
    

    约定3 model 压缩成model.gz.减少APK大小(对model可以压缩60%,格式是gz)。在内存中进行解压缩。

    zlib是个跨平台库,android只需要在链接时,加上 -lz 即可。
    解压缩函数如下:

    #include <zlib.h>
    #define CHUNK 100000
    int decodeZip(const char *source,int len,int & length,char *dest)
    {
        int ret;
        unsigned have;
        z_stream strm;
        unsigned char out[CHUNK];
        int totalsize = 0;
    
        /* allocate inflate state */
        strm.zalloc = Z_NULL;
        strm.zfree = Z_NULL;
        strm.opaque = Z_NULL;
        strm.avail_in = 0;
        strm.next_in = Z_NULL;
    
        ret = inflateInit2(&strm, 31);
    
        if (ret != Z_OK)
            return ret;
    
        strm.avail_in = len;
        strm.next_in = (unsigned char*)source;
    
        /* run inflate() on input until output buffer not full */
        do {
            strm.avail_out = CHUNK;
            strm.next_out = out;
            ret = inflate(&strm, Z_NO_FLUSH);
            switch (ret)
            {
                case Z_NEED_DICT:
                    ret = Z_DATA_ERROR; /* and fall through */
                case Z_DATA_ERROR:
                case Z_MEM_ERROR:
                    inflateEnd(&strm);
                    return ret;
            }
    
            have = CHUNK - strm.avail_out;
            memcpy(dest + totalsize ,out,have);
            totalsize += have;
    
        } while (strm.avail_out == 0);
    
        length = totalsize;
        /* clean up and return */
        inflateEnd(&strm);
        return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
    }
    

    相关文章

      网友评论

          本文标题:android平台C++代码约定

          本文链接:https://www.haomeiwen.com/subject/kyxgcxtx.html