I want to redirect the stdout
and stderr
C streams to Java, but I am struggling to do so. I used the result of this thread: https://users.jna.dev.java.narkive.com/VdgNgCIb/jna-solutions-to-catch-stdout-stderr-of-dll but it still does not work as intended.
Here is my C code (I compiled it as a TestPrintf.dll
library):
#include <stdio.h>
#include "main.h"
#include <windows.h>
void callPrintf()
{
printf("Values %d\n", 2);
}
And my Java code:
The interface for catching the stdout
stream:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class);
Pointer freopen(String filename, String mode, Pointer stream);
Pointer __iob_func();
}
The interface to access my callPrintf()
function:
import com.sun.jna.Library;
public interface MyCLibrary extends Library {
public void callPrintf();
}
And now my Java code:
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import com.sun.jna.Pointer;
import java.io.File;
public class JNATest {
public void run() {
Native.setProtected(true);
File dir = new File("D:/Java/JNATest/native");
NativeLibrary.addSearchPath("TestPrintf", dir.getPath());
CLibrary clib = CLibrary.INSTANCE;
Pointer io = clib.__iob_func();
File file = new File(dir, "stdout.txt");
clib.freopen(file.getPath(), "w", io.share(64));
MyCLibrary mylib = Native.load("TestPrintf", MyCLibrary.class);
mylib.callPrintf();
}
public static void main(String[] args) {
JNATest test = new JNATest();
test.run();
}
}
I have no exception, the C code is called correctly, the stdout.txt
file is created, but there is nothing in it.
- If I comment the
clib.freopen
line, I see the result correctly in my IDE (in my case Netbeans) output - And nothing changes if I call
fflush(stdout)
at the end of my C function - In the result of the JNA discussion I referred to above, they use
io.share(32)
rather thanio.share(64)
, but if I do that, my app crash, probably because they were still on a 32 bit platform, and mine is 64 bit.
What did I do wrong? Plus initially I did not want to create a file, but I wanted to show the catched stdout output in a TextArea in my Java app.