Skip to content
Olivier Chafik edited this page Nov 8, 2022 · 4 revisions

Summary of Java / C++ type mapping with BridJ

Introduction

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++ typeJava/BridJJNA
int*, int&, int[]Pointer<Integer>IntegerByReference, Pointer, int[], IntBuffer...
void**Pointer<Pointer<?>>PointerByReference, Pointer
wchar_tcharchar
struct S*Pointer<S>S, S.ByReference, Pointer
struct SSS.ByValue
enum EValuedEnum<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

Structs

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 :

structS {
inta;
void*p;
};
voidfunVal(structSbyVal);
structSmyStruct;
structS*pS=&myStruct;
funVal(myStruct);
funVal(*myStruct);

Equivalent Java/BridJ code :

// Generated by JNAerator :publicstaticclassSextendsStructObject {
publicS() { super(); }
publicS(Pointerpointer) { super(pointer); }
@Field(0) publicinta() {
returnthis.io.getIntField(this, 0);
}
// BridJ setters return this to allow invocation chaining@Field(0) publicSa(inta) {
this.io.setIntField(this, 0, a);
returnthis;
}
@Field(1) publicPointer<? > p() {
returnthis.io.getPointerField(this, 1, ?.class);
}
@Field(1) publicSp(Pointer<? > p) {
this.io.setPointerField(this, 1, p);
returnthis;
}
};
SmyStruct = newS(); // 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

Enums

typedefenumSimpleEnum {
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 :publicenumSimpleEnumimplementsIntValuedEnum<SimpleEnum > {
First(0),
Second(10),
Last(11);
SimpleEnum(longvalue) {
this.value = value;
}
publicfinallongvalue;
publiclongvalue() {
returnthis.value;
}
publicIterator<SimpleEnum > iterator() {
returnCollections.singleton(this).iterator();
}
publicstaticValuedEnum<SimpleEnum > fromValue(longvalue) {
returnFlagSet.fromValue(value, values());
}
};
publicstaticnativevoiddoSomething(IntValuedEnum<SimpleEnum> value);
importstaticSimpleEnum.*;
publicvoidtest {
doSomething(First);
// Pass ORed flags : 'First | Value'doSomething(SimpleEnum.fromValue(First.value() | Second.value()));
}

C++ Class

C++ code (compiled in test.dll / libtest.dylib / test.so) :

classMyClass {
public:virtual~MyClass();
intsomeMethod();
virtualintsomeVirtualMethod();
};
voidtest() {
MyClass inst;
inst.someMethod();
}

BridJ equivalent :

publicclassExample {
// Generated by JNAerator :@Library("test")
publicstaticclassMyClassextendsCPPObject {
publicMyClass() { super(); }
publicMyClass(Pointerpointer) { super(pointer);	}
@Virtual(0) publicnativevoidMyClassDestructor();
publicnativeintsomeMethod();
@Virtual(1) publicnativeintsomeVirtualMethod();
};
publicstaticvoidtest() {
MyClassinst = newMyClass();
inst.someMethod();
}
}

Clone this wiki locally