2015-01-26 148 views
1

我通过JNA从Java使用C库,并且一个函数无法正确刷新(因为输出在程序结束时一次显示)。我已经尝试了Java端System.out.flush();,但没有运气。从JNA调用libc函数

简而言之,我想从Java调用C fflush(stdout)。 JNA已经在那里(因此会更喜欢没有额外的库)并且没有C编写。

我知道JNA Library映射,如this question,但这似乎对我来说过分。

回答

2

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}); 
1

添加这个答案的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); 
    } 
}