-
Notifications
You must be signed in to change notification settings - Fork 77
BridJ is a library that lets you call C, C++ and Objective-C libraries from Java as if you were writing native code. It is a recent alternative to JNA.
With the help of JNAerator, it provides clean and unambiguous mappings to C/C++ code and a very straightforward and highly typed API to manipulate pointers, classes, structs, unions...
It bridges Java's gap when it comes to native-world interoperability.
For instance, you can allocate a new float[10]
almost as in C++ :
void someFunc(float* values);
float* array = new float[10];
float value = array[4];
someFunc(array);
delete[] array;
Scala code :
import org.bridj.Pointer._
...
@native def someFunc(values: Pointer[Float](./Float)): Unit
...
val array = allocateFloats(10)
val value = array(4)
someFunc(values)
// optional : will be eventually called by the Garbage Collector
array.release
Java code :
import org.bridj.Pointer;
import static org.bridj.Pointer.*;
...
public static native void someFunc(Pointer<Float> values);
...
Pointer<Float> array = allocateFloats(10);
float value = array.get(4);
someFunc(values);
array.release();
Read more about :
In three words : C++, Performance and Usability
Please read CurrentState
- Windows (x86, x64)
- Linux (x86, x64)
- Mac OS X (x86, x64, ppc)
- Solaris 10 (x86... soon x64 and sparc)
... with plans for FreeBSD (help and / or test hardward welcome)
If you're on Windows x86 (or on 64 bits windows in a 32 bits JVM), this is typically a case of bad calling convention being used for a native function or callback binding.
Please triple-check the calling convention (could it be __stdcall ?) and add a proper @Convention(Convention.Style.xxx)
annotation.
Short answer is : you don't need to.
Only Windows x86 has different calling conventions, so @Convention
annotations will typically be ignored silently on other platforms.
Sure, please read Build.
BridJ is dual-licensed under a very liberal BSD license and the very liberal Apache 2.0 license.
Please read HowToHelp.
BridJ is released as a self-contained JAR.
However, it includes a copy of the [ASM] library and its native library are statically linked with a modified version of https://dyncall.org Dyncall.
More details here : CreditsAndLicense.
Just paste your C header into JNAerator, choose BridJ as runtime and click on JNAerate.
On NativeLibs4Java's mailing-list.
Things BridJ aims at doing better than JNA :
- BridJ is BSD-licensed (while JNA is LGPL)
- Supports C++ (really : virtual methods, inheritance, templates...)
- Supports Objective-C, although block support is currently disabled
- Better structs : lightweight, fast (one or two orders of magnitude faster to create), without any data duplication
- Better performance in some cases:
- Direct mode is the default
- (disabled) Some calls are optimized with assembly code to reach near-JNI performance
- Supports COM (special case of C++ support) : lets you use "real" Windows APIs (IShellFolder, ITaskBarList3...)
- Cleaner API with Java 1.5 generics :
import static org.bridj.Pointer.*;
...
Pointer<Integer> p = pointerToInts(1, 2, 3, 4);
p.set(0, 10);
for (int v : p)
System.out.println("Next value : " + v);
- Typed enums (that can still be combined as flags)
- No such thing as IntByReference, LongByReference... Simply use
Pointer<Integer>
,Pointer<Long>
... - No such thing as Structure.ByReference vs. Structure.ByValue : if a function accepts a pointer to MyStruct, it's gonna be
f(Pointer<MyStruct> s)
, if it accepts a MyStruct by value it will bef(MyStruct s)
. Simple. - Wanna cast a pointer to a function pointer ?
ptr.as(MyFunctionPointer.class)
. - Pervasive multiple endianness support : if you retrieved a pointer to some GPU-filled memory and you know the GPU is little-endian while your CPU is big-endian, you can just call
myPtr.order(ByteOrder.LITTLE_ENDIAN)
. You can then retrieve data from it as usual, and even cast to a struct pointer : it will just work as intended.
Where JNA wins over BridJ :
- BridJ doesn't handle structs by value in function calls yet (neither in arguments nor in return value). This is being worked on, though.
- JNA is Java 1.4 compatible (while BridJ requires Java 1.5+)
- JNA is mature and stable, used by many projects
- BridJ supports less platforms (Windows 32/64, MacOS X Universal, Linux x86/amd64 for now)
- BridJ interfaces are harder to write by hand than JNA's. But JNAerator supports both JNA and BridJ outputs (with BridJ output being less verbose because there's only one way to bind things), so you won't need to write any interface by hand anyway.
- JNA has tons of working examples
BridJ's advantages :
- it only requires you to build your Java program, whereas SWIG requires a painful native build on every target platform
- the resulting API is generally nicer looking, without any manual configuration involved
- you work directly with the original C/C++ headers, no need to write special header as with SWIG
SWIG's advantages:
- it's C++ support is much more solid : once it compiles, you're pretty sure it's gonna work (with BridJ, errors will show up at runtime, typically at startup)
- it has support for STL types (std::string, std::vector...)
- it's more mature and stable
- JavaCL has an experimental port to BridJ (over from JNA) which is fully functional.
Please let us know if you want your project to be listed here :-)