我通过JNA从Java使用C库,并且一个函数无法正确刷新(因为输出在程序结束时一次显示)。我已经尝试了Java端System.out.flush();
,但没有运气。从JNA调用libc函数
简而言之,我想从Java调用C fflush(stdout)
。 JNA已经在那里(因此会更喜欢没有额外的库)并且没有C编写。
我知道JNA Library映射,如this question,但这似乎对我来说过分。
我通过JNA从Java使用C库,并且一个函数无法正确刷新(因为输出在程序结束时一次显示)。我已经尝试了Java端System.out.flush();
,但没有运气。从JNA调用libc函数
简而言之,我想从Java调用C fflush(stdout)
。 JNA已经在那里(因此会更喜欢没有额外的库)并且没有C编写。
我知道JNA Library映射,如this question,但这似乎对我来说过分。
JNA库包装方式代码实际上并不那么沉重(至少对于冲洗所有行为)。
protected interface CLibrary extends Library
{
static CLibrary clib = (CLibrary) Native.loadLibrary ("c", CLibrary.class);
int fflush (Pointer stream);
}
/* ... */
CLibrary.clib.fflush (null);
JNA还提供后期绑定方法和这些oneliners会做你想要什么
NativeLibrary.getInstance ("c").getFunction ("fflush").invokeInt (new Object[]{0});
// even shorter
Function.getFunction ("c", "fflush").invokeInt (new Object[]{0});
繁琐的部分来当你想限制刷新到stdout
。你必须处理vendor-specific code(STDOUT要么定义为扩展到一个数组,Amtel avr-libc一个宏,以一个函数调用,Microsoft msvcrt,或在GNU libc指针)。
对于libc中,你可以使用(两行可读性)
Pointer stdout = NativeLibrary.getInstance ("c").getGlobalVariableAddress ("stdout").getPointer (0);
Function.getFunction ("c", "fflush").invokeInt (new Object[]{stdout});
添加这个答案的Win32/Win64的用户,补充FabienAndre对GNU libc中。
选择性地清除stdout流通过JNA调用系统的C库的fflush
方法是很难和繁琐。正如FabienAndre已经提到的那样,很难弄清楚宏定义。对于msvcrt(Win32/Win64 C库),它通过对__iob_func()
的函数调用来定义;后者返回一个指向数组结构的指针。在索引0是标准输入,索引1是标准输出,索引2是标准错误。所以对于flush stdout你甚至需要知道FILE
结构的大小,当然它对于Win32和Win64是不同的......
下面的例子在Win64下测试,但是应该在Win32下工作。它受线程JNA solutions to catch stdout/stderr of DLL的启发。
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
public class JnaTest {
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("msvcrt" , CLibrary.class);
Pointer __iob_func();
void printf(String format, Object... args);
int fflush (Pointer stream);
}
public static void main(String[] args) {
int sizeOfFileStructure = Platform.is64Bit() ? 48 : 32;
Pointer stdout = CLibrary.INSTANCE.__iob_func().share(sizeOfFileStructure);
CLibrary.INSTANCE.printf("Hello, World\n");
CLibrary.INSTANCE.fflush(stdout);
}
}