android NDK开发解决打印日志的问题

  在学习trime同文输入法的时候需要打印日志。源代码中有很多DLOG() LOG()宏,于是想着借助这些宏打印日志。
如:

DLOG(INFO) << "scanning " << dirs.size() << " temp directory for log files.";

  找到这些宏所在的no_logging.h文件中的相关代码。如下:

namespace rime
{
    
    
        class VoidLogger
        {
    
    
        public:
                VoidLogger() {
    
    }

                // hack: an unnamed VoidLogger() cannot be used as an l-value
                VoidLogger &stream() {
    
     return *this; }

                template <class T>
                VoidLogger &operator<<(const T &x) {
    
     return *this; }
        };

        // to avoid compiler warnings
        class Voidify
        {
    
    
        public:
                Voidify() {
    
    }
                void operator&(VoidLogger &) {
    
    }
        };

} // namespace rime

#define RIME_NO_LOG true ? (void)0 : rime::Voidify() & rime::VoidLogger().stream()

#define DLOG(severity) LOG(severity)

  此时运行trime同文输入法时什么都不会输出。需要对重载操作法“<<”LOG()进行一些改动。

/**
 * operator 与&operator的区别:
 * 简单来说就是operator 返回的是这个值,而&operator返回的是这个的地址(引用)。
 * 主要的区别于用处就在于这个运算符的连用性,如果需要连用的话必须使用引用。
 */
template <class T>
VoidLogger &operator<<(const T &x)
{
    
    
        __android_log_print(ANDROID_LOG_INFO, "  BBB ", " %s", &x);
        return *this;
}

// LOG改为
#define LOG(severity) rime::Voidify() & rime::VoidLogger().stream() <<__LINE__<< "行 "<< __FILE__ <<" "<< __FUNCTION__ <<"() "

  这样一条LOG()会输出至少6行,每遇到一次<<就会重新换行,__FILE__也是全路径输出,并且极度消耗资源和时间。这显然不是我们想要的,得让每一条LOG输出成一行才行。继续改动VoidLogger &operator<<(const T &x)代码如下:

char fmt[550] = " ";

template <class T>
VoidLogger &operator<<(const T &x)
{
    
    
        char *str = (char *)&x;
        char *ret;

        ret = strrchr(str, '/') ? strrchr(str, '/') + 1 : str;

        strcat(fmt, ret);

        return *this;
}

  还需改Voidify类中的重载运算符“&”

// 参数表示传入的是一个VoidLogger对象的引用
void operator&(VoidLogger &vl)
{
    
    
        __android_log_print(ANDROID_LOG_INFO, " FF ", " %s", &vl.fmt);
}

  再次运行,行号、文件、函数以及参数都会打印在一行内。效果如下:

2022-04-19 04:44:59.895 10853-10853/com.osfans.trime I/ FF:  �行 setup.cc LoadModules() module_names: core

  也许你已经发现了行号根本不对,是的问题就出在这。

template <class T>
VoidLogger &operator<<(const T &x)
{
    
    
        __android_log_print(ANDROID_LOG_INFO, "BBBBBBBB", " %s", typeid(&x).name());
        return *this;
}

  当用typeid(&x).name()输出时会出现一些未知的类型,如下:

2022-04-18 22:32:18.665 29439-29439/? I/BBBBBBBB:  PKi
2022-04-18 22:32:18.665 29439-29439/? I/BBBBBBBB:  PA5_Kc
2022-04-18 22:32:18.665 29439-29439/? I/BBBBBBBB:  PA74_Kc
2022-04-18 22:32:18.665 29439-29439/? I/BBBBBBBB:  PA2_Kc
2022-04-18 22:32:18.665 29439-29439/? I/BBBBBBBB:  PA9_Kc
2022-04-18 22:32:18.665 29439-29439/? I/BBBBBBBB:  PA4_Kc
2022-04-18 22:32:18.666 29439-29439/? I/BBBBBBBB:  PA8_Kc
2022-04-18 22:32:18.666 29439-29439/? I/BBBBBBBB:  PKNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
2022-04-18 22:32:18.666 29439-29439/? I/ FF:   config_component.cc GetValue() �行  read: 1

  __LINE__的类型是int,在上面输出成了PKi。感觉非常莫名其妙!不过还有一种办法是把__LINE__转换成string类型因为C++中无法直接把int类型转换成char*类型。改动宏LOG()如下:

// LOG改为
#define STRRCHR_FILE_PATH(file_path) ((strrchr(file_path, '/') ? strrchr(file_path, '/') + 1 : file_path)[0])
#define LOG(severity) rime::Voidify() & rime::VoidLogger().stream() << (std::to_string(__LINE__))[0] << "行 " \
<< STRRCHR_FILE_PATH(__FILE__) << " " << __FUNCTION__ << "() "

输出如下:

2022-04-19 08:08:18.787 17532-17675/com.osfans.trime I/ FF:  622行 deployment_tasks.cc Run()  SymlinkingPrebuiltDictionaries

虽然任然有乱码,不过勉强能用。

猜你喜欢

转载自blog.csdn.net/yangjia_cheng/article/details/124275906
今日推荐