2012-05-25 77 views
2

我有一個使用打印的東西巧妙像的printf,logcat的和 n

printf("hello "); 
// do something 
printf(" world!\n"); 

其輸出

的Hello World的C代碼!

我想重複使用Android和iOS,但Log.d()和的NSLog(即代碼)有效每串我通過他們的末尾添加一個新行,所以這段代碼的輸出:

NSLog(@"hello "); 
// do something 
NSLog(@"world!\n"); 

出來(或多或少)爲:

你好

世界!

我願意用一些宏替換printf以使Log.d和NSLog模擬printf對'\ n'的處理;有什麼建議麼?

+0

'NSLog'不應該是'printf'的替代品,'printf'打印到'stdout'而'NSLog'用於記錄日誌文件等。 –

+0

我知道。我的問題是,如何在不破壞功能的情況下將C代碼printf重定向到移動日誌?我意識到需要一些額外的代碼。 –

回答

0

對於後代,this是我做的:在緩衝器中存儲記錄的字符串,只要有在緩衝區中的換行符換行之前打印的部分。

-1

你總是可以只建立一個字符串在段時間:

String message = "Hello"; 
// Do Something 
message += " World!"; 
Log.v("Example", message); 
+1

是的,但我希望在C中做到這一點。 –

+0

[從C打印到LogCat](http://konkanok.com/2011/02/printing-to-logcat-from-c/) – Sam

+0

謝謝,我實際上他們已經在做很多事情了。這是我追求的printf換行符。我有傳統的C代碼,它利用了printf及其新特性,我想在iOS和Android中使用它。 –

1

一種解決方案可能的工作是定義,直到找到一個換行不刷新其緩衝區一個全球性的日誌功能。

以下是一個Java一個非常簡單的Android版:

import java.lang.StringBuilder; 

class CustomLogger { 
    private static final StringBuilder buffer = new StringBuilder(); 

    public static void log(String message) { 
    buffer.append(message); 

    if(message.indexOf('\n') != -1) { 
     Log.d('SomeTag', buffer); 
     buffer.setLength(0); 
    } 
    } 
} 

... 
CustomLogger.log("Hello, "); 
// Stuff 
CustomLogger.log("world!\n"); // Now the message gets logged 

這是完全未經測試,但你的想法。
這個特定的腳本有一些性能問題。例如,檢查最後一個字符是否是換行符可能會更好。


我才意識到,你想這下應該不會太難端口雖然標準庫不會傷害(得到的東西像一個字符串緩衝區)。

0

是的,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()技術,你可以看看hereJames Moore答案)。

然後你就可以擺脫上面的功能,並定義宏爲:

#define LOG(...) fprintf(stderr, ...) 

就大功告成了。

優點:

  1. C/C++庫經常使用標準錯誤爲他們的記錄。使用dup是在logcat中輸出它們的輸出而不修改它們的代碼的唯一方法(一些大的代碼使用數百個直接調用fprintf(stderr,...))
  2. stderr是自數十年以來使用的標準C語言。所有與流相關的標準C庫函數都可以與它一起使用。對於C++也是如此,您甚至可以使用cerr和< <運算符。它在引擎蓋下工作,它仍然stderr。
  3. 非常長的行不會被截斷(相反,它們會被分割)。使用較短緩衝區的一個很好的理由(在本例中爲256)。

缺點:

  1. 在自己的線程(儘管它是一個IO只有線程,影響幾乎爲零)
  2. 沒有日誌優先級值(INFO,WARN,ERROR等。 )可以在通話過程中選擇。它使用默認的(INFO),因此DMMS將始終顯示相同顏色的stderr線條。