Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capturing stdout/stderr with NDK

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, so I can then send it by email or otherwise share it.

How can I achieve this, ideally without modifying the existing C code?

Note: this question is NOT about redirecting the output to adb or 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:

  • Why is redirecting stdout/stderr on android not working?
  • Android NDK Native LIB, What to do about existing stdio?
like image 749
Graham Borland Avatar asked Feb 08 '12 11:02

Graham Borland


2 Answers

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();
like image 123
James Moore Avatar answered Sep 30 '22 17:09

James Moore


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.

like image 43
mah Avatar answered Sep 30 '22 19:09

mah