jextract cannot generate portable code (anymore)
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Mon Jan 26 11:05:49 UTC 2026
Hi,
your solution seems good -- e.g. using canonical layout with type names
like int16_t is the right direction.
The problem is that doing so doesn't yet get us out of the woods --
because there's still C_LONG to worry about.
In your patch, you seem to address this by "downgrading" C_LONG to a
ValueLayout. This obviously works, but if we did this for every binding,
existing jextracted code using C_LONG would no longer work -- because
now the layout of C_LONG would not be sharp enough to allow you to use
it inside e.g. a MemorySegment::get call.
I think some other tactic is needed here -- either a flag that
disables/filters generation of primitive layouts (these are not defined
in any header, so filtering at the moment is not really possible). Or
adding some kind of magic auto-filtering (e.g. if C_LONG is not used
anywhere, just omit it from the bindings).
The first option is probably the simplest -- we already have many
"--include-XYZ" -- maybe also adding "--include-builtin=long" would be
ok. Although, this might create incompatibities in cases where users
have already saved the include list somewhere -- e.g.
https://github.com/manuelbl/JavaDoesUSB/blob/main/java-does-usb/jextract/linux/gen_linux.sh
E.g. currently jextract users assume that builtin types will _always_ be
emitted. The change described above would alter that.
Maurizio
On 25/01/2026 22:38, some-java-user-99206970363698485155 at vodafonemail.de
wrote:
>
> Thanks to both of you for the additional information on that!
>
> While trying to support arbitrary user-defined typedefs might indeed
> be difficult, would it be possible to at least support the standard
> fixed-width integer and floating point types (such as `int16_t`)?
> Maybe with an opt-in flag which preserves these types and generates
> corresponding constants for them in the generated `...$shared.java` class?
>
> It seems Clang does provide the needed information to get the typedef
> names and not their underlying type. I have created a proof-of-concept
> which demonstrates this here: https://github.com/openjdk/jextract/pull/299
> Hopefully this is useful for you (or anyone else), in case you weren't
> aware of it already anyway.
>
> What do you think?
>
> Kind regards
>
> Am 05.01.2026 um 13:01 schrieb Jorn Vernee:
>>
>> I had a look at what jextract does in the case of int64_t and size_t.
>> In both cases these are typedefs for another builtin type. The former
>> is a typedef for `long` and the latter a typedef for `unsigned long`.
>> jextract uses the underlying type of the typedef to determine which
>> layout to use, so we end up with C_LONG in both cases.
>>
>> While these types are semantically portable, their typedefs may have
>> a non-portable definition, which jextract expands - like a macro -
>> during extraction. This problem is similar to this example:
>>
>> #ifdef WIN32
>> typedef long long my_int;
>> #else
>> typedef long my_int;
>> #endif
>>
>> This code is portable in the C sense, but jextract eagerly picks one
>> of the two branches of this compiler switch when extracting.
>>
>> This seems like a tricky issue to workaround. In this case I think
>> we'd want the type to be 'resolved' at runtime rather than extraction
>> time, but I don't think we can let jextract collect all the different
>> definitions of `my_int`, and then pick the right one at runtime.
>>
>> Jorn
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/jextract-dev/attachments/20260126/8b3bb0f5/attachment-0001.htm>
More information about the jextract-dev
mailing list