在Java中并使用Bridj,如何动态调用任何本机函数?

时间:2015-03-25 23:34:06

标签: java clojure jna bridj

Clojure的用户通常希望尽可能地懒惰,并延迟创建类和对象。本着同样的精神,如果我想调用在Java中运行时解析的本机函数,我可以使用com.sun.jna.Function.getFunction("foolibrary", "foofuncname"),它返回com.sun.jna.Function,可以是invoked。< / p>

在Clojure中,这看起来像:

(let [f (com.sun.jna.Function/getFunction "c" "printf")]
  (.invoke f Integer (to-array ["Hello World"])))
另一方面,BridJ提供了一个有吸引力的性能优势并声称更简单的API,但是,我仍然不清楚如何使用BridJ来执行类似于运行时绑定JNA示例的操作。有人可以演示如何?此外,如果可以,这种方法是否有任何性能损失?否则,似乎提前生成Java源文件是唯一的解决方案。如果有人能证实这一点,我将不胜感激。

1 个答案:

答案 0 :(得分:2)

编辑:

更好地理解问题&amp;专注于“动态”(没有预先编译),我仍然犹豫要声称“这是不可能的”(“不可能”是一个非常强大的词/意思......就像“永远”/“从不“),但我非常确定这不是BridJ的标准程序。 我可以想到Bridj的动态解决方案,但这很可能取决于“JNAerator”,而这又取决于“JNA”(你的起始位置)。

原始答案,描述“使用BridJ动态调用任何本机函数”的“标准例程”(包括代码生成):

根据https://code.google.com/p/bridj/https://code.google.com/p/bridj/wiki/FAQ,您必须:

  1. 设置bridJ项目(java项目+ bridJ依赖项)
  2. 针对您的lib运行the JNAerator(带有bridJ输出选项)。这将生成Java文件,这些文件用作导出函数的“存根/委托”。
  3. 这些“存根”可以由您的Java代码引用/使用,并且(应该)调用您的库。
  4. 取自“他们的快速启动”的样本:

      

    原始C ++代码:

    /// exported in test.dll / libtest.so / libtest.dylib
    class MyClass {
       public:
          MyClass();
          ~MyClass();
          virtual void virtualMethod(int i, float f);
          void normalMethod(int i);
    };
    void getSomeCount(int* countOut);
    ...
    void test() {
      int count;
      getSomeCount(&count);
      MyClass t;
      t.virtualMethod(count, 0.5f);
    }
    
      

    与BridJ的翻译+绑定:

    (这是生成的java代码)

    import org.bridj.*;     // C interop and core classes
    import org.bridj.ann.*; // annotations
    import org.bridj.cpp.*; // C++ runtime
    import static org.bridj.Pointer.*; // pointer factories such as allocateInt(), pointerTo(java.nio.Buffer), etc...
    
    @Library("test")
    public class TestLibrary {
       static {
          BridJ.register(); // binds all native methods in this class and its subclasses
       }
       public static class MyClass extends CPPObject {
          @Virtual(0) // says virtualMethod is the first virtual method
          public native void virtualMethod(int i);
          public native void normalMethod(int i);
       };
       public static native void getSomeCount(Pointer<Integer> countOut);
    
       public static void test() {
          Pointer<Integer> pCount = allocateInt();
          getSomeCount(pCount);
          MyClass t = new MyClass();
          t.virtualMethod(pCount.get(), 0.5f);
      }
    }
    

    希望这有帮助!