<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <p>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.<br>
      <br>
      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:<br>
      <br>
      <font face="monospace">#ifdef WIN32<br>
        typedef long long my_int</font><font face="monospace">;<br>
        #else<br>
        typedef long </font><font face="monospace">my_int</font><font face="monospace"></font><font face="monospace">;<br>
        #endif</font></p>
    <p>This code is portable in the C sense, but jextract eagerly picks
      one of the two branches of this compiler switch when extracting.</p>
    <p>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.</p>
    <p>Jorn</p>
    <div class="moz-cite-prefix">On 29-12-2025 23:43,
      <a class="moz-txt-link-abbreviated" href="mailto:some-java-user-99206970363698485155@vodafonemail.de">some-java-user-99206970363698485155@vodafonemail.de</a> wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:7f755534-64eb-42f5-bd6e-b0c8371f992f@vodafonemail.de">
      
      <p>Hello,</p>
      <p>the jextract guide [1] says that jextract can generate portable
        code if the C code on which it is executed is portable.<br>
        That seems to be no longer the case due to <a class="moz-txt-link-freetext" href="https://bugs.openjdk.org/browse/CODETOOLS-7903923" moz-do-not-send="true">https://bugs.openjdk.org/browse/CODETOOLS-7903923</a>.
        There are two problems:</p>
      <ul>
        <li>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"</li>
        <li>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.<br>
          Take for example
          <a class="moz-txt-link-freetext" href="https://github.com/tree-sitter/java-tree-sitter/blob/master/scripts/jextract.sh" moz-do-not-send="true">https://github.com/tree-sitter/java-tree-sitter/blob/master/scripts/jextract.sh</a>
          which runs jextract for
          <a class="moz-txt-link-freetext" href="https://github.com/tree-sitter/tree-sitter/blob/master/lib/include/tree_sitter/api.h" moz-do-not-send="true">https://github.com/tree-sitter/tree-sitter/blob/master/lib/include/tree_sitter/api.h</a><br>
          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.<br>
          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).</li>
      </ul>
      <p>jextract version: Build 25-jextract+2-4 (2025/11/25)</p>
      <p>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?<br>
        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)?<br>
        Or a way for jextract to not convert `int64_t` and `size_t` to
        C_LONG, if that is possible? </p>
      <p>Or is there possibly also a problem with the <a class="moz-txt-link-freetext" href="https://github.com/tree-sitter/java-tree-sitter" moz-do-not-send="true">https://github.com/tree-sitter/java-tree-sitter</a>
        setup mentioned above? For example is there a way to make
        jextract refer to `int64_t` in the generated code instead of
        `C_LONG`?</p>
      <p>Kind regards</p>
      <p><br>
      </p>
      <p>[1]
        <a class="moz-txt-link-freetext" href="https://github.com/openjdk/jextract/blob/b96ad6618a70ddbdf6b67cc3eb8342efc39c0692/doc/GUIDE.md?plain=1#L103-L111" moz-do-not-send="true">https://github.com/openjdk/jextract/blob/b96ad6618a70ddbdf6b67cc3eb8342efc39c0692/doc/GUIDE.md?plain=1#L103-L111</a></p>
    </blockquote>
  </body>
</html>