使用 NDK 捕获 stdout/stderr

发布于 2025-01-03 23:14:33 字数 564 浏览 3 评论 0原文

我正在移植一些现有的 C 代码以在 Android 上运行。此 C 代码将大量输出写入 stdout/stderr。我需要在内存缓冲区或文件中捕获此输出,以便我可以通过电子邮件发送或以其他方式共享它。

理想情况下,我怎样才能实现这一目标而不修改现有的 C 代码?

注意:这个问题与将输出重定向到 adb 或 logcat 无关;我需要在设备上本地缓冲输出。我知道以下问题似乎无法解决我的查询:

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:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

ら栖息 2025-01-10 23:14:33

使用类似的方法将 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();

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();
隔岸观火 2025-01-10 23:14:33

stdout 是路径 1,stderr 是路径 2。了解了这一点,您可以建立想要作为输出目标的新路径,然后将它们强制到 stdout 和/或 stderr。 实际示例使用 dup 或 dup2 中有一个示例展示了如何执行此操作。

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.

蹲在坟头点根烟 2025-01-10 23:14:33

我使用了詹姆斯·摩尔提交的答案,但我希望能够打开和关闭日志记录。这样我可以将 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);

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文