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++ 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

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 :

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

Enums

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++ Class

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();
	}
}
Clone this wiki locally