-
Notifications
You must be signed in to change notification settings - Fork 77
TypeMapping
If it's a pointer, it's a Pointer !
With BridJ, mapping was kept to its simplest form : if a type is a pointer, it will be mapped to org.bridj.Pointer in Java (or to a subclass of it). This is very different from JNA where there are many possible mappings for the same native type.
C/C++ type |
Java/BridJ | JNA |
---|---|---|
int* , int& , int[]
|
Pointer<Integer> |
IntegerByReference , Pointer , int[] , IntBuffer ... |
void** |
Pointer<Pointer<?>> |
PointerByReference , Pointer
|
wchar_t |
char |
char |
struct S* |
Pointer<S> |
S , S.ByReference , Pointer
|
struct S |
S |
S.ByValue |
enum E |
ValuedEnum<E> |
int |
const char* |
Pointer<Byte> (use getCString() to get the string) |
String , Pointer , ByteByReference , ByteBuffer , byte[]
|
Note that while NIO buffers are not allowed in bindings (Pointer<Integer>
must be used rather than IntBuffer
, unlike with JNA), it is trivial to create pointers out of buffers (see Pointer.pointerToBuffer(Buffer)
, Pointer.pointerToInts(IntBuffer)
...) and the other way around (Pointer.getBuffer()
, Pointer.getIntBuffer()
...).
Please make sure to also read the FAQ
BridJ structs were designed to be performant and easy to use.
Using JNAerator to create them out of C definitions is strongly advised.
C code :
struct S {
int a;
void* p;
};
void funVal(struct S byVal);
struct S myStruct;
struct S* pS = &myStruct;
funVal(myStruct);
funVal(*myStruct);
Equivalent Java/BridJ code :
// Generated by JNAerator :
public static class S extends StructObject {
public S() { super(); }
public S(Pointer pointer) { super(pointer); }
@Field(0)
public int a() {
return this.io.getIntField(this, 0);
}
// BridJ setters return this to allow invocation chaining
@Field(0)
public S a(int a) {
this.io.setIntField(this, 0, a);
return this;
}
@Field(1)
public Pointer<? > p() {
return this.io.getPointerField(this, 1, ?.class);
}
@Field(1)
public S p(Pointer<? > p) {
this.io.setPointerField(this, 1, p);
return this;
}
};
S myStruct = new S(); // maybe chained with setters : new S().a(10).b(12).c(55);
Pointer<S> pS = Pointer.getPointer(myStruct);
funVal(myStruct);
funVal(myStruct.get()); // pointer is a reified generic class, so get() returns a correct S instance
typedef enum SimpleEnum {
First = 0,
Second = 10,
Last = 11
} SimpleEnum;
Enums don't mean the same in Java and C/C++.
- In Java, an enum item is a singleton subclass of the enum class. It has no associated value besides its index within the list of enum items but is a real class and can implement interfaces and define new fields / methods
- In C/C++, enums are just typed integers (in C++ they're not restricted to int), so you can combine them with bitwise operators
&
,|
,^
,!
...
This means that we'd like to benefit from the enum / singleton Java pattern and still be able to pass multiple values to C code expecting enums.
In BridJ, this is made possible with the ValuedEnum<E>
interface (and IntValuedEnum<E>
subinterface) :
// Generated by JNAerator :
public enum SimpleEnum implements IntValuedEnum<SimpleEnum > {
First(0),
Second(10),
Last(11);
SimpleEnum(long value) {
this.value = value;
}
public final long value;
public long value() {
return this.value;
}
public Iterator<SimpleEnum > iterator() {
return Collections.singleton(this).iterator();
}
public static ValuedEnum<SimpleEnum > fromValue(long value) {
return FlagSet.fromValue(value, values());
}
};
public static native void doSomething(IntValuedEnum<SimpleEnum> value);
import static SimpleEnum.*;
public void test {
doSomething(First);
// Pass ORed flags : 'First | Value'
doSomething(SimpleEnum.fromValue(First.value() | Second.value()));
}
C++ code (compiled in test.dll / libtest.dylib / test.so) :
class MyClass {
public:
virtual ~MyClass();
int someMethod();
virtual int someVirtualMethod();
};
void test() {
MyClass inst;
inst.someMethod();
}
BridJ equivalent :
public class Example {
// Generated by JNAerator :
@Library("test")
public static class MyClass extends CPPObject {
public MyClass() { super(); }
public MyClass(Pointer pointer) { super(pointer); }
@Virtual(0)
public native void MyClassDestructor();
public native int someMethod();
@Virtual(1)
public native int someVirtualMethod();
};
public static void test() {
MyClass inst = new MyClass();
inst.someMethod();
}
}