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

In Java and using Bridj, how can you dynamically invoke any native function?

Clojure 的用户通常希望尽可能地懒惰,并延迟 类 和对象的创建。本着同样的精神,如果我想调用一个在运行时从 Java 中解析的本机函数,我可以使用 com.sun.jna.Function.getFunction("foolibrary", "foofuncname"),其中 returns 和 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 源文件是唯一的解决方案。如果有人能证实这一点,我将不胜感激。

编辑:

在更好地理解了问题并专注于“动态”(没有预编译)之后,我仍然犹豫是否声称 "it is impossible"("impossible" 是一个非常强大的word/meaning ...像"always"/"never"),但我非常确定这不是BridJ的标准例程。 我可以想到 Bridj 的动态解决方案,但这很可能取决于 "JNAerator",而这又取决于 "JNA"(您的起始位置)。

原答案,描述"standard routine" for "dynamically invoke any native function with BridJ"(涉及代码生成):

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

  1. 设置 bridJ 项目(java 项目 + bridJ 依赖项)
  2. 运行 the JNAerator(使用 bridJ 输出选项)针对您的库。这将生成 Java 文件,作为导出函数的 "stubs/delegates"。
  3. 这些 "stubs" 可以通过您的 java 代码 referenced/used,并且(应该)调用您的库。

样本取自"their Quickstart":

Original C++ code :

/// 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);
}

Translation + binding with 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);
  }
}

希望对您有所帮助!