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

bmi*_*are 5 java clojure jna bridj

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

在Clojure中,它看起来像:

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

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

xer*_*593 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(带有 bridJ 输出选项)。这将生成 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);
}
Run Code Online (Sandbox Code Playgroud)

翻译 + 与 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);
  }
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!