2015-01-26 115 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); 
    } 
}