6

Often users of Clojure wish to be as lazy as possible, and delay the creation of classes and objects. In that same spirit, if I wish to invoke a native function which is resolved during runtime from within Java, I can use com.sun.jna.Function.getFunction("foolibrary", "foofuncname"), which returns a com.sun.jna.Function, which can be invoked.

In Clojure this looks like:

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

BridJ, on the other hand, offers an attractive performance benefit and claimed simplier API, however, it is still not clear to me how to use BridJ to do something similar to the runtime binding JNA example. Can someone demonstrate how? Also, if this is possible, are there any performance penalties with this approach? Otherwise, it appears generating the Java source file ahead of time is the only solution. I would appreciate it if someone could confirm this.

Magnilex
  • 11,584
  • 9
  • 62
  • 84
bmillare
  • 4,183
  • 2
  • 23
  • 42

1 Answers1

4

Edit:

After better understanding the question & focusing on "dynamically" (without pre-compilation), I still hesitate to claim "it is impossible" ("impossible" is a very strong word/meaning ...like "always"/"never"), but I am very sure that this is not the standard routine of BridJ. I can think of a dynamical solution with Bridj, but this would be very probably dependent from "JNAerator" and this in turn would be dependent from "JNA" (your starting position).

The original answer, describing the "standard routine" for "dynamically invoke any native function with BridJ" (involving code generation):

According to https://code.google.com/p/bridj/ and https://code.google.com/p/bridj/wiki/FAQ, you'll have to:

  1. Set up a bridJ project (java project + bridJ dependencies)
  2. Run the JNAerator (with bridJ output option) against your libs. This will generate Java files, which serve as "stubs/delegates" for your exported functions.
  3. These "stubs" can be referenced/used by your java code, and (should) invoke your libs.

Sample taken from "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 :

(this is generated java code)

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

Hope this helps!

xerx593
  • 12,237
  • 5
  • 33
  • 64
  • 1
    I think I was not clear enough about my question and I've updated the wording. I'm asking if runtime/delayed binding is possible. Your answer requires generating java code which must be compiled and loaded ahead-of-time, rather than just-in-time. – bmillare Apr 06 '15 at 21:58
  • ok, i think i get you clearer, but I also fear that this is not featured by BridJ. (no way around JNAerator ... definitely not within 2-3 lines!) I would stick with your current product, which is also "not standard java" btw. but (formerly) this https://java.net/projects/jna/ and currently this https://github.com/twall/jna/ project/product. – xerx593 Apr 06 '15 at 22:28
  • An answer stating it's not possible is still a valid answer. I'll give you the points if nothing else comes up in the next remaining hours. – bmillare Apr 06 '15 at 22:39
  • To be pedantic, if you could modify the text of your answer to state that it's not featured by Bridj, then I'll accept your answer. Thanks – bmillare Apr 07 '15 at 14:13