从JNA调用libc函数

时间:2015-01-26 20:24:31

标签: jna libc

我通过JNA从Java使用C库,并且一个函数没有正确刷新(因为输出在程序结束时一次显示)。我没试过Java边System.out.flush();

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

我知道this question中的JNA库映射,但这对我来说似乎有点过分了。

2 个答案:

答案 0 :(得分:2)

JNA库包装方式代码实际上并不那么重(至少对于flush all行为)。

protected interface CLibrary extends Library
{
  static CLibrary clib = (CLibrary) Native.loadLibrary ("c", CLibrary.class);
  int fflush (Pointer stream);
}

/* ... */
  CLibrary.clib.fflush (null);

JNA还提供后期绑定方法,这些oneliner会做你想做的事情

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 msvcrtGNU libc中的指针) 。

对于libc,您可以使用(两行易读性)

Pointer stdout = NativeLibrary.getInstance ("c").getGlobalVariableAddress ("stdout").getPointer (0);
Function.getFunction ("c", "fflush").invokeInt (new Object[]{stdout});

答案 1 :(得分:1)

为Win32 / Win64用户添加此答案,补充FabienAndre用于GNU libc。

选择性地刷新stdout流,通过jna调用系统的c库的fflush方法是困难和繁琐的。正如FabienAndre已经提到的那样,很难掌握stdout宏定义。对于msvcrt(Win32 / Win64 C库),它通过对__iob_func()的函数调用来定义;后者返回一个指向FILE结构数组的指针。索引0是stdin,索引1是stdout,索引2是stderr。因此,对于刷新标准版,你甚至需要知道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);
  }
}