Skip to content
squid233 edited this page Oct 15, 2023 · 11 revisions

OverrunGL is designed base on Java FFM API.

Interact with Native Libraries

To invoke the functions of the native libraries, we don’t use JNI native method or other JNI-like libraries, but we use method handles.

Method Handles

To invoke a native function, we need to create a downcall handle.

Linker.nativeLinker().downcallHandle(lookup.find("nativeFunction").get(), FunctionDescriptor.of(...));

SymbolLookup::find returns a nullable Optional of MemorySegment, so we can use Optional::orElseThrow to throw an exception when the function is not found.

We can also pass an address of a function pointer, because downcallHandle accepts MemorySegment.

handle = downcallHandle(GLFW.getProcAddress(arena, "glGetString") /* it returns a MemorySegment */, FunctionDescriptor.of(ADDRESS, JAVA_INT));

Invoking

MethodHandle::invoke or invokeExact throws a Throwable, so we have to catch it or add it to method signature.

We just rethrow the exception we caught, so we can see what happened and create an issue.

try {
    handle.invokeExact(...);
} catch (Throwable e) {
    throw new AssertionError("should not reach here", e);
}

C Types -> Java Types

FunctionDescriptor is a carrier of the memory layouts. We use a corresponding FunctionDescriptor to pass and get the values.

The types in the table this below are directly converted from/to C.

Value Layout Parameter Type C/C++ Type
JAVA_BYTE byte char
JAVA_SHORT short short
JAVA_INT int int
JAVA_LONG long long long
JAVA_CHAR char short
JAVA_BOOLEAN boolean char/bool
JAVA_FLOAT float float
JAVA_DOUBLE double double
ADDRESS MemorySegment void*

Any pointer types can directly convert to MemorySegment even if it is a pointer of struct or other pointers of pointer.

✔️ int*
✔️ my_struct*
✔️ void**
✔️ other_struct******

ValueLayout.ADDRESS with target layout on return type will reinterpret to correspoding size.

Naming Convention

OverrunGL removes the prefix of the macros and functions when the wrapper class name is similar to it.

// C: glfwInit()
GLFW.init();
// C: glGetString()
GL10C.getString();
// or
GL.getString();
// C: glfwGetInstanceProcAddress, should be used with static import
GLFWVulkan.glfwGetInstanceProcAddress();
Clone this wiki locally