6

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

在 Clojure 中,这看起来像:

(let [f (com.sun.jna.Function/getFunction "c" "printf")]
  (.invoke f Integer (to-array ["Hello World"])))

另一方面,BridJ 提供了有吸引力的性能优势并声称 API 更简单,但是,我仍然不清楚如何使用 BridJ 来执行类似于运行时绑定 JNA 示例的操作。有人可以演示如何吗?此外,如果这是可能的,这种方法是否有任何性能损失?否则,似乎提前生成 Java 源文件是唯一的解决方案。如果有人能证实这一点,我将不胜感激。

4

1 回答 1

4

编辑:

在更好地理解了这个问题并专注于“动态”(没有预编译)之后,我仍然犹豫声称“这是不可能的”(“不可能”是一个非常强烈的词/含义......就像“总是”/“从不” ),但我确定这不是 BridJ 的标准套路。我可以想到一个使用 Bridj 的动态解决方案,但这很可能取决于“JNAerator”,而这又取决于“JNA”(你的起始位置)。

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

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

  1. 建立一个bridJ项目(java项目+bridJ依赖)
  2. 针对您的库运行JNAerator(带有 briJ 输出选项)。这将生成 Java 文件,这些文件用作导出函数的“存根/委托”。
  3. 这些“存根”可以由您的 java 代码引用/使用,并且(应该)调用您的库。

样本取自“他们的快速入门”:

原始 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);
  }
}

希望这可以帮助!

于 2015-04-06T20:43:23.697 回答