2012-02-08 12 views
13

Sto eseguendo il porting di un codice C esistente per l'esecuzione su Android. Questo codice C scrive molto output su stdout/stderr. Ho bisogno di catturare questo output, sia in un buffer di memoria o un file, quindi posso quindi inviarlo via e-mail o altrimenti condividerlo.Acquisizione di stdout/stderr con NDK

Come posso ottenere ciò, idealmente senza modificare il codice C esistente?

Nota: questa domanda è NON sul reindirizzamento dell'output ad adb o logcat; Ho bisogno di bufferizzare l'output localmente sul dispositivo. Sono consapevole delle seguenti domande, che non sembrano affrontare la mia domanda:

+0

C++ http://stackoverflow.com/questions/8870174/is-stdcout-usable-in-android-ndkl –

risposta

1

stdout è percorso 1 e stderr è percorso 2. Sapendo questo, è possibile stabilire nuovo percorso (s) che si desidera essere la destinazione di uscita, quindi costringerli in stdout e/o stderr. C'è un esempio che mostra come farlo a practical examples use dup or dup2.

+0

vorrei far notare che non c'è nulla di speciale in Android qui. Questo è il modo normale di fare cose sulla maggior parte dei sistemi unix-like. –

17

Utilizzare qualcosa come questo per reindirizzare lo stderr in una pipe. Avere un lettore sul lato opposto della scrittura tubo per 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); 
    } 
} 

ti consigliamo di eseguire questo nel proprio thread. Mi filare il filo in Java e quindi avere il filo chiamata Java questo codice NDK come questo:

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

Questo codice perde un descrittore di file - dovresti 'close (pipes [1]') dopo la chiamata a 'dup2()'. Inoltre, dovresti controllare gli errori, anche se non sono sicuro di cosa faresti se una di queste chiamate di sistema fallisse. –

1

ho usato la risposta presentata da James Moore, ma volevo essere in grado di trasformare la registrazione on e off. Con questo posso mettere mKeepRunning su false e si spegne. Dovevo anche aggiungere il flag O_NONBLOCK al file in modo che non fosse più una chiamata di blocco.

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); 
Problemi correlati