Захват stdout / stderr с помощью NDK - PullRequest
15 голосов
/ 08 февраля 2012

Я портирую некоторый существующий код C для работы на Android.Этот код C записывает много выходных данных в stdout / stderr.Мне нужно захватить этот вывод, либо в буфере памяти, либо в файле, чтобы я мог затем отправить его по электронной почте или иным образом поделиться им.

Как я могу добиться этого, в идеале, без изменения существующего кода C?

Примечание: этот вопрос НЕ о перенаправлении вывода в adb или logcat;Мне нужно буферизовать вывод локально на устройстве.Мне известны следующие вопросы, которые не соответствуют моему запросу:

Ответы [ 3 ]

19 голосов
/ 13 июня 2012

Используйте что-то вроде этого, чтобы перенаправить stderr в канал. Попросите читателя на другой стороне трубы написать в 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);
    }
}

Вы захотите запустить это в своем собственном потоке. Я раскручиваю поток в Java, а затем поток Java вызывает этот код NDK следующим образом:

new Thread() {
    public void run() {
        nativePipeSTDERRToLogcat();
    }
}.start();
1 голос
/ 30 марта 2015

Я использовал ответ, предоставленный Джеймсом Муром, но я хотел иметь возможность включать и выключать регистрацию.Благодаря этому я могу установить для mKeepRunning значение false, и он будет отключен.Мне также нужно было добавить флаг 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);
1 голос
/ 08 февраля 2012

stdout - это путь 1, а stderr - это путь 2. Зная это, вы можете установить новые пути, которые вы хотите использовать в качестве выходного пункта назначения, а затем преобразовать их в stdout и / или stderr.В есть пример, показывающий, как это сделать, на практических примерах используется dup или dup2 .

...