I have C code that uses prints with something clever like
printf("hello ");
// do something
printf(" world!\n");
which outputs
hello world!
I want to reuse that code with Android and iOS, but Log.d() and NSLog() effectively add a newline at the end of every string I pass them, so that the output of this code:
NSLog(@"hello ");
// do something
NSLog(@"world!\n");
comes out (more or less) as:
hello
world!
I'm willing to replace printf with some macro to make Log.d and NSLog emulate printf's handling of '\\n'; any suggestions?
One solution that might work is to define a global log function that doesn't flush its buffer until it finds a newline.
Here's a (very) simple version in java for 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
It's completely untested but you get the idea.
This particular script has some performance issues. It might be better to check if just the last character is a newline for example.
I just realized that you wanted this in C. It shouldn't be too hard to port though a standard lib wouldn't hurt (to get stuff like a string buffer).
对于后代, 这就是我所做的:将记录的字符串存储在缓冲区中,并在缓冲区中有换行符时在换行符之前打印该部分。
Yes, the NDK logcat is dumb about it. There are ways to redirect stderr/stdout to logcat, but there are drawbacks (either need to "adb shell setprop" which is only for rooted devices, or a dup() like technique but creating a thread just for that purpose is not a good idea on embedded devices IMHO though you can look further below for this technique).
So I did my own function/macros for that purpose. Here are snippets. In a debug.c, do this:
#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);
}
Then in debug.h do this:
#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__)
...
Now you just need to include debug.hpp and call LOGI() with a printf-like semantic buffered until a '\\n' is encountered (or buffer is full).
This is not perfect though, as if the string generated from a call is longer than the buffer, it will be truncated and output. But frankly, 1024 chars should be enough in most cases (even less than this). Anyway, if this happens it will output a warning so you know about it.
Also note the vsnprintf() is not standard C (but it works in Android NDK). We could use vsprintf() instead (which is standard), but it is unsafe on its own.
======================================================================
Now for the dup() technique, you can look here ( James Moore answer).
Then you can get rid of the function above and define your macro as:
#define LOG(...) fprintf(stderr, ...)
and you're done.
Advantages:
Disadvantages:
You could always just build the string one segment at a time:
String message = "Hello";
// Do Something
message += " World!";
Log.v("Example", message);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.