我正在移植一些现有的C代码以在Android上运行。此C代码将大量输出写入stdout / stderr。我需要在内存缓冲区或文件中捕获此输出,以便我可以通过电子邮件或其他方式共享它。
如何在不修改现有C代码的情况下实现这一目标?
注意:关于将输出重定向到adb或logcat,此问题 NOT ;我需要在设备上本地缓冲输出。我知道以下问题,这些问题似乎无法解决我的问题:
答案 0 :(得分:18)
使用类似的东西将stderr重定向到管道。让管道另一侧的读者写入logcat:
extern "C" void Java_com_test_yourApp_yourJavaClass_nativePipeSTDERRToLogcat(JNIEnv* env, jclass cls, jobject obj)
{
int pipes[2];
pipe(pipes);
dup2(pipes[1], STDERR_FILENO);
FILE *inputFile = fdopen(pipes[0], "r");
char readBuffer[256];
while (1) {
fgets(readBuffer, sizeof(readBuffer), inputFile);
__android_log_write(2, "stderr", readBuffer);
}
}
你想在自己的线程中运行它。我在Java中启动线程然后让Java线程调用这个NDK代码:
new Thread() {
public void run() {
nativePipeSTDERRToLogcat();
}
}.start();
答案 1 :(得分:1)
stdout是路径1,stderr是路径2.知道这一点,你可以建立你想成为输出目的地的新路径,然后将它们强制转换为stdout和/或stderr。有一个示例显示如何在practical examples use dup or dup2处执行此操作。
答案 2 :(得分:1)
我使用了James Moore提交的答案,但我希望能够打开和关闭日志。有了这个,我可以将mKeepRunning设置为false,它将关闭。我还需要将O_NONBLOCK标志添加到文件中,因此它不再是阻塞调用。
int lWriteFD = dup(STDERR_FILENO);
if ( lWriteFD < 0 )
{
// WE failed to get our file descriptor
LOGE("Unable to get STDERR file descriptor.");
return;
}
int pipes[2];
pipe(pipes);
dup2(pipes[1], STDERR_FILENO);
FILE *inputFile = fdopen(pipes[0], "r");
close(pipes[1]);
int fd = fileno(inputFile);
int flags = fcntl(fd, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(fd, F_SETFL, flags);
if ( nullptr == inputFile )
{
LOGE("Unable to get read pipe for STDERR");
return;
}
char readBuffer[256];
while (true == mKeepRunning)
{
fgets(readBuffer, sizeof(readBuffer), inputFile);
if ( strlen(readBuffer) == 0 )
{
sleep(1);
continue;
}
__android_log_write(ANDROID_LOG_ERROR, "stderr", readBuffer);
}
close(pipes[0]);
fclose(inputFile);