Generating a common interface for multiple platform specific binding

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Fri Jan 6 11:15:08 UTC 2023


Really good progress!

On 06/01/2023 10:31, Martin Pernollet wrote:
> Hi everyone,
>
> Thank you a lot for your messages. I got good news to share :
>
>   * First, I have been able to render the OpenGL teapot /inside/ a
>     Swing and AWT window \o/ Please see the video attached or even try
>     it on your macOS here
>     <https://urldefense.com/v3/__https://gitlab.com/jzy3d/panama-gl/-/blob/main/panama-gl-wrappers-macos/src/main/java/demos/panamagl/macos/swing/DemoTeapot_Onscreen_macOS.java__;!!ACWV5N9M2RV99hQ!Kml55Ybj-rpsn3N8SEjStiscqW8Ma0NJklvvm_C6lYscfvg2Y8qEDk_fJLbitlLqV4ZvtoW5kfz9q_NBqkWJJWQNXyD0UYeAzE3yAg$>.
>   * Second, I confirm that I running bindings generated for macOS
>     10.15 runs on 10.12.
>
Good to know
>
> The pattern I am going toward for a common interface
>
>   * Have generated bindings, generated once and deployed asstandalone
>     maven artifacts
>     <https://urldefense.com/v3/__https://gitlab.com/jzy3d/panama-gl-bindings__;!!ACWV5N9M2RV99hQ!Kml55Ybj-rpsn3N8SEjStiscqW8Ma0NJklvvm_C6lYscfvg2Y8qEDk_fJLbitlLqV4ZvtoW5kfz9q_NBqkWJJWQNXyD0UYfNbASRsQ$>.
>   * Have wrappers of these bindings
>     <https://urldefense.com/v3/__https://gitlab.com/jzy3d/panama-gl/-/blob/main/panama-gl-wrappers-macos/src/main/java/opengl/macos/GL_macOS_10_15_7.java__;!!ACWV5N9M2RV99hQ!Kml55Ybj-rpsn3N8SEjStiscqW8Ma0NJklvvm_C6lYscfvg2Y8qEDk_fJLbitlLqV4ZvtoW5kfz9q_NBqkWJJWQNXyD0UYcr23qqcA$>
>     implementing a common interface
>     <https://urldefense.com/v3/__https://gitlab.com/jzy3d/panama-gl/-/blob/main/panama-gl-core/src/main/java/opengl/GL.java__;!!ACWV5N9M2RV99hQ!Kml55Ybj-rpsn3N8SEjStiscqW8Ma0NJklvvm_C6lYscfvg2Y8qEDk_fJLbitlLqV4ZvtoW5kfz9q_NBqkWJJWQNXyD0UYeHQ6CP_A$>.
>
>
Do you think that that the same set of bindings will not work across OS? 
Why?
>
> I will generate the common interface and the wrappers. I am thinking 
> of using Javaassist 
> <https://urldefense.com/v3/__http://www.javassist.org/__;!!ACWV5N9M2RV99hQ!Kml55Ybj-rpsn3N8SEjStiscqW8Ma0NJklvvm_C6lYscfvg2Y8qEDk_fJLbitlLqV4ZvtoW5kfz9q_NBqkWJJWQNXyD0UYdt6zOTJQ$>. 
> I am interested if you have other suggestions.

Other options, if you are into classfile manipulation are:

* ASM (perhaps the more popular, what the JDK itself uses): 
https://asm.ow2.io/
* the brand new JDK classfile API: 
https://mail.openjdk.org/pipermail/classfile-api-dev/2022-June/000000.html

>
> To answer the "well-behave" nature of OpenGL
>
>   * Yes, there are types to hide differences per platform. OpenGL is
>     an API so one can expect to find the same headers everywhere.
>   * BUT OpenGL has dynamic loading capabilities to allow getting
>     features on computers that have hardware (GPU) supporting some
>     kind of rendering, and others not able to do the same, still
>     running on the same OS but not the same GPU. That is a very
>     interesting case for Panama. In that case I'll have to rely on
>     OpenGL API methods that load functions only if they are supported
>     on the host computer.
>
I think you refer to GL extensions - aren't there like opaque function 
pointers whose existence you can query dynamically? I think stuff like 
this can be made to work well with Panama. Other projects such as the 
Fuse Panama port are using similar function-pointer based approaches:

https://github.com/cryptomator/jfuse

That said, the fact that there are extensions, doesn't mean that the 
jextract bindings would not be portable across OSs ? But more that you 
need to write some kind of support to discover and invoke the extension 
functions? (wild guess here)

>
> A bit more about OpenGL
>
>   * Sometime I have to ask the OS to do things such as executing java
>     runnable on the main macOS thread. For now this requires I keep
>     using manually generated binding from JOGL, allowing to use
>     Objective C code. I don't think JExtract can do this
>     <https://urldefense.com/v3/__https://github.com/manuelbl/JavaDoesUSB/issues/5__;!!ACWV5N9M2RV99hQ!Kml55Ybj-rpsn3N8SEjStiscqW8Ma0NJklvvm_C6lYscfvg2Y8qEDk_fJLbitlLqV4ZvtoW5kfz9q_NBqkWJJWQNXyD0UYfPT9ePYA$>.
>
Does passing this option " -XstartOnFirstThread" to the JVM works? IIRC, 
it was added for things like these. I think I saw this here:

https://foojay.io/today/project-panama-for-newbies-part-3/

Which does have an opengl tutorial for MacOs

>   * There are several additional libraries to GL and GLUT, handling OS
>     specific things (e.g. CGL for mac, WGL for windows, GLX for
>     linux). I'll most probably bind to these rather than glut.
>
Ok - so this part is not portable, and you will need different bindings 
for each OS, which seems ok.
>
> The JavaDoesUSB project is really great and its developer has been 
> really nice by providing help on JExtract, thank you for the advice!
Maurizio
>
> ------- Original Message -------
> Le mardi 3 janvier 2023 à 18:51, Maurizio Cimadamore 
> <maurizio.cimadamore at oracle.com> a écrit :
>
>>
>> On 20/12/2022 15:04, Martin Pernollet wrote:
>>> Here's my use case in more detail : I've been advised to generate 
>>> *different binding for different OS* (and maybe version). For 
>>> OpenGL, this lead me to a glut_h binding for macOS, one for Windows 
>>> and one for Linux.
>>
>> Expanding a bit more on this point (apologies if my previous reply 
>> was not clear).
>>
>> While we suggest that, in the general case, one might have to run 
>> jextract multiple times (once per target platform), your mileage my vary.
>>
>> Consider the jextract code. Jextract relies on libclang, a native 
>> library. For jextract itself, we just generate a single copy of the 
>> bindings for both MacOS, Linux and Windows:
>>
>> https://github.com/openjdk/jextract/tree/master/updateclang
>>
>> This is possible because libclang has been written in a portable way: 
>> for instance types that are platform dependent such as `long` have 
>> been expanded to `long long`, so that they are 64 bits no matter what.
>>
>> Also, the API makes extensive use of the opaque handle pattern: that 
>> is, a lot of libclang data structures are built inside the library 
>> itself, and then returned to clients as opaque by-value structs, 
>> whose contents point to the memory allocated by the library.
>>
>> As such, the layouts of the structs defined in libclang is never 
>> truly important, as a client will typically pass them opaquely to 
>> other functions.
>>
>> The combination of these two factors allow the bindings to work 
>> seamlessly across platforms.
>>
>> Now, while I'm not an expert on OpenGL, I seem to recall that OpenGL 
>> is rather well-behaved when it comes to defining new types - e.g. it 
>> defines its own primitives (GLint, GLfloat and such). This gives me 
>> some hope that the OpenGL bindings might, in fact, work well across 
>> multiple platforms.
>>
>> One complication with OpenGL is GLUT, which doesn't seem (IIRC) to be 
>> well supported on some platforms (e.g. MacOS). So, some tricks might 
>> be necessary there.
>>
>> I guess the main takeaway there is that IF (big if :-)) the library 
>> has been written in a portable way, then a single jextract run might 
>> be all you need (maybe with some filtering added on top to get rid of 
>> platform-dependent functionalities, which you can do with the 
>> jextract options already available).
>>
>> The USB code [1] I pointed you at, on the other hand, is much more 
>> complex, as that code needs to interface with _different_ libraries 
>> to do its job on different platforms - so of course that kind of 
>> unification is not something you can achieve using a tool.
>>
>> So, as often is the case with native code, we have a spectrum of 
>> "badness":
>>
>> 1) well-behaved libraries (like libclang and OpenGL), which are 
>> written with portability in mind
>> 2) libraries that are mostly portable, but might present minor 
>> mismatches (e.g. long being 64 vs. 32 bits, some API points not 
>> available in all platforms, etc.)
>> 3) libraries that are hopelessly platform-specific
>>
>> I believe jextract proves that (1) already works (**). And for (3), 
>> as stated, not much can be done.
>>
>> So the question is whether something should be done for (2) - and how 
>> much can be done "automagically". This will likely require us to come 
>> up with a precise definition of the boundaries of what gaps we can 
>> actually bridge, as (2) is a rather fuzzy bucket.
>>
>> (**) I can see ways in which even libraries in bucket (1) could fail 
>> - e.g. this can happen because the symbol lookup would fail to 
>> initialize because of different library names/paths. This is 
>> something that we need to address, but also something which requires 
>> a much much smaller hammer (such as the ability to define your own 
>> symbol lookup).
>>
>> Cheers
>> Maurizio
>>
>> [1] - https://github.com/manuelbl/JavaDoesUSB
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/panama-dev/attachments/20230106/2185c056/attachment-0001.htm>


More information about the panama-dev mailing list