With the release of JDK 22 the new Foreign Function & Memory API (FFM API) has been introduced from preview phase.
This API is intended to substitute Java Native Interface (JNI) and become a standard of interacting with native code from Java.
While FFM API itself is very powerful and can provide access to onheap/offheap memory segments and call a native function, it is lacking of extended features of converting C/C++ structures to Java classes.
Of course, we have jextract
tool, but the code it generates is kind of messy and hard to understand.
This project goal is to combine the power of FFM API and Java, like annotation processing, to make you happy while working with native functions and structures.
- two separate libraries -
annotation
andannotation-processor
working with code generation during compile time - C/C++ types support in top level: struct, union, enum (including anonymous and opaque)
- context based generation: combine several native libraries within one code base
- can load third party native libraries or use already loaded by classloader
- flexible native-to-java function declarations
- pass to native functions primitives and objects, by value or just a pointer
- java exceptions with the power of errno/strerr
- safe and clean code generation
- useful helpers to work with structures, like
.createEmpty()
- ready to write your project unit tests with generated native structures
JDK22+
with FFM API enabled ( use--enable-native-access=ALL-UNNAMED
run parameter or addEnable-Native-Access: ALL-UNNAMED
to jar manifest file)glibc 2.31+
(ubuntu 20.04+ or MacOS Sonoma+) on host machine where annotation processor is running (requirement forlibclang
). Windows hosts are not yet supported.
- Add dependencies to your
build.gradle
:
dependencies {
// Annotations to use for code generation
implementation 'io.github.digitalsmile.native:annotation:${version}'
// Process annotations and generate code at compile time
annotationProcessor 'io.github.digitalsmile.native:annotation-processor:${version}'
}
- Define interface class and run your build:
@NativeMemory(header = "gpio.h")
@Structs
@Enums
public interface GPIO {
@NativeManualFunction(name = "ioctl", useErrno = true)
int nativeCall(int fd, long command, int data) throws NativeMemoryException;
}
This code snippet will generate all structures and enums within the header file gpio.h
(located in resources
folder), as well as GPIONative
class with call implementation of ioctl
native function.
Observe concepts in doucmentation or find more examples in getting started. You can also look at tests or in my other project https://github.com/digitalsmile/gpio
- Enjoy! :)
- more support of native C/C++ types and patterns
- validation of structures parameters and custom validation support