jextract cannot generate portable code (anymore)
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Mon Jan 5 10:12:12 UTC 2026
Hi,
I agree this is an issue that needs to be looked at. Note that the
problem you refer to is that the mismatch between extraction-time and
runtime is now more explicit, and results in a cast error. Before, the
declaration of C_LONG would have gone through, but with the wrong layout.
The key to define a portable library is to make sure builtin types are
basically never used -- if a library is truly portable, and defines its
own primitive types.
That said, even a well-behaved portable library, like OpenGL, ends up
having some dependencies on builtin types:
```
typedef float GLfloat; /* single precision float */
```
So, having a flag to remove the definition of builtin types will likely
backfire.
It would be nice if there was a mechanism to extend the filtering
mechanism to builtin types. So, if long is problematic for your
bindings, you could just leave it out. (which is also what we do for
jextract libclang bindings).
Maurizio
On 29/12/2025 22:43, some-java-user-99206970363698485155 at vodafonemail.de
wrote:
>
> Hello,
>
> the jextract guide [1] says that jextract can generate portable code
> if the C code on which it is executed is portable.
> That seems to be no longer the case due to
> https://bugs.openjdk.org/browse/CODETOOLS-7903923. There are two problems:
>
> * On Windows it generates `OfInt C_LONG`, on non-Windows `OfLong
> C_LONG`. But it looks up the layout dynamically using
> `canonicalLayouts().get(...)`. Regardless of whether the generated
> code actually uses `C_LONG` you will get a ClassCastException
> during initialization when trying for example to use code
> generated on Linux on a Windows machine: "ClassCastException:
> class jdk.internal.foreign.layout.ValueLayouts$OfIntImpl cannot be
> cast to class java.lang.foreign.ValueLayout$OfLong"
> * The general approach of using `canonicalLayouts().get(...)` seems
> to make this non-portable (even if the code declared `C_LONG` as
> the general `ValueLayout` instead of the specific `OfInt` /
> `OfLong`, avoiding the ClassCastException), because jextract
> converts types such as `size_t` and `int64_t` to `C_LONG` on
> Linux, even though these types are defined in `canonicalLayouts()`
> as well.
> Take for example
> https://github.com/tree-sitter/java-tree-sitter/blob/master/scripts/jextract.sh
> which runs jextract for
> https://github.com/tree-sitter/tree-sitter/blob/master/lib/include/tree_sitter/api.h
> Note that `api.h` is (if I see it correctly) portable. However for
> `int64_t` (used by `ts_tree_cursor_goto_first_child_for_byte`)
> jextract uses the non-portable `C_LONG` on Linux.
> Another problem are `calloc` and `malloc` where jextract treats
> `size_t` as non-portable `C_LONG` as well (I guess `size_t` would
> be portable at least across 64 bit platforms, or would fail with a
> ClassCastException if not, as desired).
>
> jextract version: Build 25-jextract+2-4 (2025/11/25)
>
> Note sure what a good solution to this is. Maybe an opt-out CLI flag
> for the CODETOOLS-7903923 behavior, and an update to GUIDE.md?
> That would make code generated with jextract on Linux portable to
> Windows again I think. Or are there cases where CODETOOLS-7903923 is
> really needed (even for portable C libraries)?
> Or a way for jextract to not convert `int64_t` and `size_t` to C_LONG,
> if that is possible?
>
> Or is there possibly also a problem with the
> https://github.com/tree-sitter/java-tree-sitter setup mentioned above?
> For example is there a way to make jextract refer to `int64_t` in the
> generated code instead of `C_LONG`?
>
> Kind regards
>
>
> [1]
> https://github.com/openjdk/jextract/blob/b96ad6618a70ddbdf6b67cc3eb8342efc39c0692/doc/GUIDE.md?plain=1#L103-L111
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/jextract-dev/attachments/20260105/fc911a79/attachment.htm>
More information about the jextract-dev
mailing list