简体   繁体   English

使用NDK捕获stdout / stderr

[英]Capturing stdout/stderr with NDK

I am porting some existing C code to run on Android. 我正在移植一些现有的C代码以在Android上运行。 This C code writes lots of output to stdout/stderr. 此C代码将大量输出写入stdout / stderr。 I need to capture this output, either in a memory buffer or a file, so I can then send it by email or otherwise share it. 我需要在内存缓冲区或文件中捕获此输出,以便我可以通过电子邮件或其他方式共享它。

How can I achieve this, ideally without modifying the existing C code? 如何在不修改现有C代码的情况下实现这一目标?

Note: this question is NOT about redirecting the output to adb or logcat; 注意:这个问题不是关于将输出重定向到adb或logcat; I need to buffer the output locally on the device. 我需要在设备上本地缓冲输出。 I am aware of the following questions, which do not appear to address my query: 我知道以下问题,但似乎没有解决我的问题:

Use something like this to redirect stderr to a pipe. 使用类似的东西将stderr重定向到管道。 Have a reader on the other side of the pipe write to logcat: 让管道另一端的读者写入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);
    }
}

You'll want to run this in its own thread. 你想在自己的线程中运行它。 I spin up the thread in Java and then have the Java thread call this NDK code like this: 我在Java中启动线程,然后让Java线程调用这个NDK代码,如下所示:

new Thread() {
    public void run() {
        nativePipeSTDERRToLogcat();
    }
}.start();

I used the answer submitted by James Moore, but I wanted to be able to turn the logging on and off. 我使用了James Moore提交的答案,但我希望能够打开和关闭日志。 With this I can set the mKeepRunning to false and it will shut down. 有了这个,我可以将mKeepRunning设置为false,它将关闭。 I also needed to add the O_NONBLOCK flag to the file so it was no longer a blocking call. 我还需要将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);

stdout is path 1 and stderr is path 2. Knowing this, you can establish new path(s) that you want to be the output destination, then coerce them into stdout and/or stderr. stdout是路径1,stderr是路径2.知道了这一点,你可以建立你想成为输出目的地的新路径,然后将它们强制转换为stdout和/或stderr。 There's an example showing how to do this at practical examples use dup or dup2 . 有一个例子说明如何在实际例子中使用dup或dup2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM