是的,NDK logcat的是啞巴吧。有很多方法可以將stderr/stdout重定向到logcat,但是有一些缺點(需要「adb shell setprop」,它只適用於根目錄的設備,或者類似dup()的技術,但是爲此目的創建一個線程並不是一件好事關於嵌入式設備的想法恕我直言,雖然你可以看看這個技術下面)。
所以,我做我自己的函數/宏用於這一目的。這裏是片段。在debug.c,做到這一點:
#include "debug.h"
#include <stdio.h>
#include <stdarg.h>
static const char LOG_TAG[] = "jni";
void android_log(android_LogPriority type, const char *fmt, ...)
{
static char buf[1024];
static char *bp = buf;
va_list vl;
va_start(vl, fmt);
int available = sizeof(buf) - (bp - buf);
int nout = vsnprintf(bp, available, fmt, vl);
if (nout >= available) {
__android_log_write(type, LOG_TAG, buf);
__android_log_write(ANDROID_LOG_WARN, LOG_TAG, "previous log line has been truncated!");
bp = buf;
} else {
char *lastCR = strrchr(bp, '\n');
bp += nout;
if (lastCR) {
*lastCR = '\0';
__android_log_write(type, LOG_TAG, buf);
char *rest = lastCR+1;
int len = bp - rest; // strlen(rest)
memmove(buf, rest, len+1); // no strcpy (may overlap)
bp = buf + len;
}
}
va_end(vl);
}
然後在debug.h做到這一點:
#include <android/log.h>
void android_log(android_LogPriority type, const char *fmt, ...);
#define LOGI(...) android_log(ANDROID_LOG_INFO, __VA_ARGS__)
#define LOGW(...) android_log(ANDROID_LOG_WARN, __VA_ARGS__)
...
現在你只需要包括debug.hpp,並用類似printf調用LOGI()語義緩衝直到遇到'\ n'(或緩衝區已滿)。
雖然這並不完美,就好像從調用中產生的字符串比緩衝區長,但它會被截斷並輸出。但坦率地說,在大多數情況下1024個字符應該是足夠的(甚至比這少)。無論如何,如果發生這種情況,它會輸出一個警告,讓你知道它。
還要注意vsnprintf()不是標準的C(但它在Android NDK中有效)。我們可以使用vsprintf()來代替(這是標準的),但它本身並不安全。
============================================== ========================
現在爲dup()技術,你可以看看here(James Moore答案)。
然後你就可以擺脫上面的功能,並定義宏爲:
#define LOG(...) fprintf(stderr, ...)
就大功告成了。
優點:
- C/C++庫經常使用標準錯誤爲他們的記錄。使用dup是在logcat中輸出它們的輸出而不修改它們的代碼的唯一方法(一些大的代碼使用數百個直接調用fprintf(stderr,...))
- stderr是自數十年以來使用的標準C語言。所有與流相關的標準C庫函數都可以與它一起使用。對於C++也是如此,您甚至可以使用cerr和< <運算符。它在引擎蓋下工作,它仍然stderr。
- 非常長的行不會被截斷(相反,它們會被分割)。使用較短緩衝區的一個很好的理由(在本例中爲256)。
缺點:
- 在自己的線程(儘管它是一個IO只有線程,影響幾乎爲零)
- 沒有日誌優先級值(INFO,WARN,ERROR等。 )可以在通話過程中選擇。它使用默認的(INFO),因此DMMS將始終顯示相同顏色的stderr線條。
'NSLog'不應該是'printf'的替代品,'printf'打印到'stdout'而'NSLog'用於記錄日誌文件等。 –
我知道。我的問題是,如何在不破壞功能的情況下將C代碼printf重定向到移動日誌?我意識到需要一些額外的代碼。 –