Erfassen von stdout/stderr mit NDK

Lesezeit: 2 Minuten

Benutzer-Avatar
Graham Borland

Ich portiere einen vorhandenen C-Code für die Ausführung auf Android. Dieser C-Code schreibt viele Ausgaben nach stdout/stderr. Ich muss diese Ausgabe entweder in einem Speicherpuffer oder in einer Datei erfassen, damit ich sie dann per E-Mail senden oder anderweitig teilen kann.

Wie kann ich dies erreichen, idealerweise ohne den bestehenden C-Code zu ändern?

Hinweis: Diese Frage ist NICHT über das Umleiten der Ausgabe an adb oder logcat; Ich muss die Ausgabe lokal auf dem Gerät puffern. Mir sind die folgenden Fragen bekannt, die meine Anfrage anscheinend nicht beantworten:

  • Warum funktioniert die Umleitung von stdout/stderr auf Android nicht?
  • Android NDK Native LIB, was tun mit vorhandenem stdio?

  • C++ stackoverflow.com/questions/8870174/…

    – Ciro Santilli Путлер Капут 六四事

    16. Februar 2016 um 13:51 Uhr


Benutzer-Avatar
James Moore

Verwenden Sie so etwas, um stderr zu einer Pipe umzuleiten. Lassen Sie einen Leser auf der anderen Seite der Pipe in logcat schreiben:

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);
    }
}

Sie sollten dies in einem eigenen Thread ausführen. Ich drehe den Thread in Java hoch und lasse dann den Java-Thread diesen NDK-Code wie folgt aufrufen:

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

  • Dieser Code gibt einen Dateideskriptor preis – das sollten Sie close(pipes[1]) nach dem Aufruf an dup2(). Außerdem sollten Sie nach Fehlern suchen, obwohl ich nicht ganz sicher bin, was Sie tun würden, wenn einer dieser Systemaufrufe fehlschlägt.

    – Adam Rosenfield

    23. August 2013 um 22:02 Uhr

Benutzer-Avatar
Mah

stdout ist Pfad 1 und stderr ist Pfad 2. Wenn Sie dies wissen, können Sie neue Pfade einrichten, die Sie als Ausgabeziel verwenden möchten, und sie dann in stdout und/oder stderr zwingen. Es gibt ein Beispiel, das zeigt, wie man dies bei praktischen Beispielen mit dup oder dup2 macht.

  • Ich möchte darauf hinweisen, dass Android hier nichts Besonderes ist. Dies ist die normale Vorgehensweise auf den meisten Unix-ähnlichen Systemen.

    – James Moore

    12. Juni 2012 um 22:29 Uhr

Benutzer-Avatar
GR-Gesandter

Ich habe die Antwort von James Moore verwendet, aber ich wollte die Protokollierung ein- und ausschalten können. Damit kann ich mKeepRunning auf false setzen und es wird heruntergefahren. Ich musste der Datei auch das O_NONBLOCK-Flag hinzufügen, damit es kein blockierender Anruf mehr war.

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

1056290cookie-checkErfassen von stdout/stderr mit NDK

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy