Capturing stdout/stderr with NDK

前端 未结 3 751
渐次进展
渐次进展 2020-12-09 04:57

I am porting some existing C code to run on Android. This C code writes lots of output to stdout/stderr. I need to capture this output, either in a memory buffer or a file,

相关标签:
3条回答
  • 2020-12-09 05:06

    I used the answer submitted by James Moore, but I wanted to be able to turn the logging on and off. With this I can set the mKeepRunning to false and it will shut down. I also needed to add the O_NONBLOCK flag to the file so it was no longer a blocking call.

        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);
    
    0 讨论(0)
  • 2020-12-09 05:09

    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. There's an example showing how to do this at practical examples use dup or dup2.

    0 讨论(0)
  • 2020-12-09 05:22

    Use something like this to redirect stderr to a pipe. Have a reader on the other side of the pipe write to 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:

    new Thread() {
        public void run() {
            nativePipeSTDERRToLogcat();
        }
    }.start();
    
    0 讨论(0)
提交回复
热议问题