manuelbl / JavaDoesUSB

USB library for Java
MIT License
136 stars 10 forks source link

Generating wrappers of macOS SDK Foundation framework #5

Closed jzy3d closed 1 year ago

jzy3d commented 1 year ago

@manuelbl I have been advised to explore your work to go further with JExtract/Panama that I use to generate Java bindings to OpenGL.

You seam to be experienced at generating bindings to macOS SDK frameworks so I'd like to ask how you deal with surprising cases such as in Foundation/NSObjCRuntime.h at line 492. The @class keyword does not seam to be regular C language to me.

#define NSFoundationVersionNumber_iOS_9_x_Max 1299
#endif

@class NSString, Protocol;

typedef NSString * NSExceptionName NS_EXTENSIBLE_STRING_ENUM;
typedef NSString * NSRunLoopMode NS_EXTENSIBLE_STRING_ENUM;

Here is JExtract output:

./panama-gl-bindings-macos/include/Foundation/NSObjCRuntime.h:492:1: error: expected identifier or '('

How did you deal with this kind of line?

manuelbl commented 1 year ago

The code you're showing is clearly Objective-C code. This won't work. And the problem likely is that it was picked for processing in the first place. Unfortunately, your question doesn't show what command caused the problem.

My approach for dealing with macOS frameworks can be seen at https://github.com/manuelbl/JavaDoesUSB/tree/main/java-does-usb/jextract/macos. Translated to the GLUT framework, it looks like this (for JDK 19 / jextract 19):

Don't include the framework header file directly. Instead create a helper file using the #include statement with angular brackets:

opengl_helper.h

#include <GLUT/glut.h>

Clang (jextract) will correctly resolve such include statements if the -F option points to the macOS SDK. In the current jextract version, this unfortunately can only be specified with a separate compile_flags.txt file:

compile_flags.txt

-F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks

Then call jextract like so:

#!/bin/sh

JEXTRACT=../../jextract-19/bin/jextract
# If SDK_DIR is changed, it needs to be changed in compile_flags.txt as well.
SDK_DIR=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk

$JEXTRACT --source --output src/generated/java \
  -I $SDK_DIR/usr/include \
  -lGLUT.framework \
  --source \
  --header-class-name GLUT \
  --target-package opengl.macos \
  opengl_helper.h

This will generate 266 files. The file RuntimeHelper.java needs to be modified. The following lines need to be deleted:

        System.loadLibrary("GLUT.framework");
        SymbolLookup loaderLookup = SymbolLookup.loaderLookup();

and then replaced with:

        SymbolLookup loaderLookup = SymbolLookup.libraryLookup("GLUT.framework/GLUT", MemorySession.openImplicit());
jzy3d commented 1 year ago

Thank you a lot for taking time to answer with details.

I have been able to generate the binding for GLUT that I made available here if you are interested.

I had a slightly different approach to deal with other macOS SDK.

I first define links toward all folder that I want to include :

sudo ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers AppKit
sudo ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers Foundation
sudo ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreFoundation.framework/Versions/A/Headers CoreFoundation

So that I can later refer to a single include folder that Clang properly handle.

Then if I want AppKit I do this

/Library/Java/JavaVirtualMachines/jdk-17.jdk-panama/Contents/Home/bin/jextract \
  -d ./panama-gl-bindings-macos/src/generated/java/ \
  --source -t opengl.appkit.macos.v10_15_7 \
  -I  ./panama-gl-bindings-macos/include \
  -I /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/ \
  -C-F./panama-gl-bindings-macos/include \
./panama-gl-bindings-macos/include/AppKit/AppKit.h

I tried to generate bindings to AppKit.h with the hope to have Java bindings allowing to do something similar to OSXmisc.m in JOGL - which starts by including AppKit.

However the function I want to reproduce with Panama has non C/C++ code inside, so this might not work from Panama :(

Maybe I'll have to keep this in pure JNI and mainly bind to GL/GLU/GLUT/CGL with Panama.

Thanks for having cleanly documented your project, that was really instructive for me!

manuelbl commented 1 year ago

Ah, so you were trying to use the AppKit framework.

It seems that the majority of frameworks are Objective-C frameworks. They cannot be used from C and thus not from Panama either.

I don't have a list of C vs Objective-C frameworks. But if grep finds matches for #import in the Versions/Current/Headers subdirectory, it seems to be an Objective-C framework.

jzy3d commented 1 year ago

Thank you a lot, your answer help a lot on bumping my project to JDK19 :)

jzy3d commented 1 year ago

This will generate 266 files. The file RuntimeHelper.java needs to be modified. The following lines need to be deleted:

        System.loadLibrary("GLUT.framework");
        SymbolLookup loaderLookup = SymbolLookup.loaderLookup();

For your information : I also add to delete

System.loadLibrary("OpenGL.framework");