我通過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);
}
}