6

我有一个用 C 开发的大程序,大多数函数都有几 fprintf(stderr, "message")行。

但现在我需要在 Java 程序中使用这些函数。所以,我实现了一个JNI接口在Java和C之间进行通信。一切正常,Java和C可以通信,但是现在我想在Java中捕获C的几个stderr......我该怎么做?

干杯;)

4

4 回答 4

1

根据我对同样问题的经验,我可以看出 JNI 桥对通过标准流从 JNI 输出的重要性有非常奇怪的看法。通常它会进行大量缓存,溢出不可预测的块和时间,我们没有弄清楚如何强制刷新。

我们最终*printf()用记录到文件的方式对语句进行了大规模正则表达式替换,完全在 C 端完成。跟踪生成的日志文件比任何试图让 JVM 相信当 C 层这么说时你确实需要日志记录的尝试更可靠,而不是当 JVM 决定缓冲区时。

于 2012-11-15T15:43:26.140 回答
0

基于这个答案,我认为你应该能够重新分配进程的 stderr。您将需要另一个线程在 JNI 函数执行时从中读取数据,以免它阻塞。

于 2012-11-15T00:46:40.830 回答
0

当您调用 JNI 库时,会将其加载到 JVM 进程中,因此库 STDOUT 和 STDERR 将是 JVM STDOUT 和 STDERR。所以问题是特定于操作系统的,更像是“进程如何读取自己的 STDOUT/STDERR?”

有几种可能性内部捕获/重定向标准输出?,但我认为仅读取库的 STDOUT 或 STDERR 并不容易(我认为在我给您的示例中,一旦执行重定向,您就无法返回使用控制台进行输出(*))。

正如所评论的,答案将在很大程度上取决于您的操作系统。

(*) 我可能错了,我对 C/系统编程不是很精通。

于 2012-11-15T00:40:09.227 回答
0

一种可能的解决方法是执行以下操作,可在http://www.thecodingforums.com/threads/redirect-cout-and-cerr-to-system-out-and-system-err.635861/找到

我想出的解决方案是使用两种方法创建一些 JNI 代码:

  • 将标准输出重定向到管道的一种
  • 一个将输出存储在那里的

然后流是:

  • 调用重定向的函数
  • 进行多个其他 JNI 调用
  • 获取输出并将其写入我想要的位置

上面链接提供的实现如下所示

#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <jni.h>

#include "Nat1.h"

#define MAXBUF 20480

static int oldstdout;
static int pipehandles[2];
static char buf[MAXBUF];

JNIEXPORT void JNICALL Java_Nat2_init(JNIEnv *cntx, jobject me)
{
    oldstdout = _dup(_fileno(stdout));
    _pipe(pipehandles,MAXBUF,_O_BINARY);
    _dup2(pipehandles[1],_fileno(stdout));
 }

JNIEXPORT jstring JNICALL Java_Nat2_done(JNIEnv *cntx, jobject me)
{
    int n;
    fflush(stdout);
    _dup2(oldstdout,_fileno(stdout));
    n = _read(pipehandles[0],buf,sizeof(buf));
    buf[n] = '\0';
    return (*cntx)->NewStringUTF(cntx,buf);
}

这有点麻烦,因为您需要开始捕获标准错误,然后在以后想要查看它时获取它。

于 2016-04-15T06:45:24.940 回答