我有一个用 C 开发的大程序,大多数函数都有几
fprintf(stderr, "message")
行。
但现在我需要在 Java 程序中使用这些函数。所以,我实现了一个JNI接口在Java和C之间进行通信。一切正常,Java和C可以通信,但是现在我想在Java中捕获C的几个stderr......我该怎么做?
干杯;)
我有一个用 C 开发的大程序,大多数函数都有几
fprintf(stderr, "message")
行。
但现在我需要在 Java 程序中使用这些函数。所以,我实现了一个JNI接口在Java和C之间进行通信。一切正常,Java和C可以通信,但是现在我想在Java中捕获C的几个stderr......我该怎么做?
干杯;)
根据我对同样问题的经验,我可以看出 JNI 桥对通过标准流从 JNI 输出的重要性有非常奇怪的看法。通常它会进行大量缓存,溢出不可预测的块和时间,我们没有弄清楚如何强制刷新。
我们最终*printf()
用记录到文件的方式对语句进行了大规模正则表达式替换,完全在 C 端完成。跟踪生成的日志文件比任何试图让 JVM 相信当 C 层这么说时你确实需要日志记录的尝试更可靠,而不是当 JVM 决定缓冲区时。
基于这个答案,我认为你应该能够重新分配进程的 stderr。您将需要另一个线程在 JNI 函数执行时从中读取数据,以免它阻塞。
当您调用 JNI 库时,会将其加载到 JVM 进程中,因此库 STDOUT 和 STDERR 将是 JVM STDOUT 和 STDERR。所以问题是特定于操作系统的,更像是“进程如何读取自己的 STDOUT/STDERR?”
有几种可能性内部捕获/重定向标准输出?,但我认为仅读取库的 STDOUT 或 STDERR 并不容易(我认为在我给您的示例中,一旦执行重定向,您就无法返回使用控制台进行输出(*))。
正如所评论的,答案将在很大程度上取决于您的操作系统。
(*) 我可能错了,我对 C/系统编程不是很精通。
一种可能的解决方法是执行以下操作,可在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);
}
这有点麻烦,因为您需要开始捕获标准错误,然后在以后想要查看它时获取它。