5 This is various experiments with the panama-foreign abi JEP for
6 invoking native C functions from Java directly and without JNI.
8 The main goal is to experiment with creating a "java friendly" and
9 mostly type-safe api directly in one step, without requiring
12 It uses a gcc plugin to compile c headers to obtain most of the api
13 information, but requires cpp and perl to extract the values of
14 #define constants as they are not available to the gcc plugin.
16 This api information is then converted to Java code using a
17 config-directed perl script `export-api'. The config file can be used
18 to create static (all-in-one) or object oriented output. It includes
19 templated strings as well as perl fragments to generate various source
22 The vulkan api is officially defined by a registry in xml, so there's
23 a separate generator for that.
28 Requirements are gcc and GNU cpp, perl, GNU make, and of course a
29 compatible jdk-foreign jdk. The various modules require headers or
30 sdks for their corresponding libraries, e.g. ffmpeg-5.x,
33 Copy config.make.in to config.make and modify any variables required.
35 First compile the native binding tools. This should only need to be
36 done once after which it auto-updates properly.
40 Then make everything else, parallel make should work.
48 Or run a demo (see next section):
50 $ make run-notzed.vkregistry/vulkan.test.TestVulkan
52 A non-recursive make setup is used although make file fragments are
53 included from various locations across the modules. All java is
56 JAVA_HOME must point to a compatible panama-enabled jdk.
58 The latest at the time of writing was:
60 branch: foreign-jextract
61 commit: 2e1291680024f12fbf2f0f02b0f79d7b4348b369
62 date: Fri Feb 4 11:01:21 2022 +0000
64 All output and intermediate files are in bin/
66 bin/modules/<module>/classes - compiled java modules
67 bin/gen/<module>/classes - generated java
68 bin/gen/<module>/gen - generated intermediate non-java
70 These are more or less an exploded view of all jmod files:
72 bin/<target>/bin - commands for all modules
73 bin/<target>/lib - libraries/config and modular jar files for all modules
74 bin/<target>/include - header files for all modules
78 bin/<target>/jmods - .jmod modules
84 Most examples have a demo, see the <module>_JMAIN variables in the
85 Makefile for the targets. They are executed using:
87 $ make run-<module>/<main-class>
92 notzed.nativez contains some support classes and the code generator.
93 The gcc plugin source is in src/notzed.nativez/native/ the code
94 generator is in src/notzed.nativez/{bin,lib}.
96 notzed.api is a pseudo-module containing a simple test c api for
97 experiments, it just builds into a library.
99 notzed.apistatic is a 'all in one class' static wrapper for
102 notzed.apiobject is an object-oriented wrapper for notzed.api.
104 notzed.clstatic is an 'all in one class' static wrapper for OpenCL
105 (2.1). The api closesly matches the C api except it converts error
106 codes into exceptins and can infer certain arguments from others such
107 as length parameters. This is probably the most complete api.
109 notzed.ffmpeg is a partial object-oriented mapping for ffmpeg-5.0 that
110 closely follows the jjmpeg design. It's enough to read video frames.
111 The demo requires a file 'movie.api' in the root directory to run.
113 notzed.vkheader uses the header-based generator on the vulkan
114 installed headers. This is still very incomplete work in progress.
115 Much meta-data is lost such as which functions are extensions during
116 the generation of the headers. This is incomplete and dead-ended.
118 notzed.vkregistry uses a completely different generator which directly
119 parses the official xml registry specification for vulkan
120 (/usr/share/vulkan/registry/vk.xml). This is directly converted to
121 about-as-java-friendly a vulkan api as one can hope for, particularly
122 the constructors for all the config objects. This is incomplete and
125 notzed.vulkan also uses a different generator which directly parses
126 the official xml registry specification for vulkan
127 (/usr/share/vulkan/registry/vk.xml). This version uses templates to
128 generate the various structures in more concise and relatively
129 consistenet way. Work in progress.
134 The main generator is written in perl and lives in
135 src/notzed.nativez/{bin,lib}.
139 * run the gcc plugin to extract all of the available c structures from
140 gcc and save them to a perl hash.
142 gcc plugins aren't very well documented so it was a lot of trial and
143 error to get it to output all the type information even starting
144 with a partial example. The names of parameters for function calls
145 were particularly problematic.
147 * optionally run export-defines to extract #define constants. They
148 can be grouped/excluded by name or by the filename they belong to.
149 The the first rule to match will complete the processing for a given
152 This is also a surprisingly difficult process because the c
153 pre-processor can just generate arbitrary c expressions so the only
154 way to find their correct value is to execute the c. So the export
155 script generates a c file which is compiled and executed to generate
156 the perl definitions.
158 Currently the types are mapped to a 'compatible' native type by
159 using the gcc operators __builtin_choose_expr,
160 __builtin_types_compatible_p, and typeof to implement a
161 pseudo-function overloading in c - possiblly using c++ is a better
162 choice here. For now inclusions or exclusions are required to
163 avoid problematic definitions that confuse these operators.
165 These files are then fed to generate-api. It proceeds in multiple
168 First stages are handled by lib/api.pm.
170 * Load and preprocess the api definition.
172 - Perform a bunch of 'fix up' processing on the data structures such
173 as inserting anonymous types which are not generated by the plugin.
175 - Create a full dependency tree for the objects
176 specificallyreferenced by the api definition so only objects and
177 functions of interest are included.
179 - Resolve all the various export options using some rules and store
180 the information about the selected options onto target objects.
182 Then generate-api produces the java files from a combination of the
183 processed data definitions and the api definition.
185 * Export 'libraries'. These are static classes of functions and/or
188 - Can include static methods. Methods can have per-method template
191 - Can include constants.
193 * Export 'structures'. These represent C pointers.
195 - struct/union have a MemorySegment, a layout, and potentially
196 accessors for fields.
198 - anonymous structures just have a MemoryAddress and no accessors.
200 - Can include static and member methods. Methods can have per-method
203 - Can include constants.
205 * Export 'calls'. These are function interfaces for function pointers.
207 - The interface is the java form of the call.
209 - If available a typedef name is used, otherwise the names are mapped
210 to a mangled name of the form Call_<args>_<return>.
212 - An upcall factory creates an upcall to an instance of a hidden
213 trampline interface which performs the mapping of arguments to java
216 - A downcall factory creates a downcall which maps the java call to
219 - Both factories return a record of type FunctionPointer<type> which
220 contains both a NativeSymbol and the java interface instance so they
221 can be used from either environment.
223 * Export 'constants'. These are referenced enums or any defines which
224 haven't been included in any other library or struct.
226 - enums are mapped to an interface with fields of:
227 'static final int FOO = xx'
229 'static final long FOO = xx'
231 - defines are mapped to a matching native type which includes
232 floating point types and strings in addition to all the integral
235 lib/code.pm is used to generate some of the code and handle
236 templating. Common code templates are defined in lib/code.api but can
237 be extended or replaced by a given api file.
239 lib/method.pm is used to generate per-field (struct) and per-argument
240 (function) sub-templates for mapping c to and from java. The
241 sub-templates it uses are defined in lib/types.api but again they can
242 be extended or replaced by a given api file.
247 It's all very much work in progress and due to the constant changes in
248 panama will be in flux for some time.
250 * bitfields are implemented.
251 * varargs is not implemented.
252 * the generator for notzed.vkregistry uses a lot of miserable
254 * the scope and object lifecycle stuff is not really sorted out yet.
255 * the config format and features are still being fiddled with.
256 * the config file isn't really documented.
257 * the build system is still being fiddled with, some of the output
258 directories are mixed up.
259 * linux-amd64 only at this point in time.
264 GNU General Public License, version 3 or later, but see individual
265 file headers for specifics.
270 * https://www.zedzone/software/panamaz.html - project page.
271 * https://openjdk.java.net/projects/panama - openjdk panama page.
272 * https://github.com/openjdk/panama-foreign - openjdk panama source.