I can get my JNI class to only partially execute due to my unfamiliarity with Objective-C and JNF. What I've tried so far is as follows:
Here's Open.java
import java.awt.event.*;import javax.swing.*;public class Open extends JFrame { public Open () { getContentPane().add(new JButton(new AbstractAction() { public void actionPerformed (ActionEvent e) { try { NativeOpenFileDialog.run(); } catch (Throwable ex) { System.err.println(ex.getMessage()); } } })); pack(); setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { new Open(); } }); }}
Here's NativeOpenFileDialog.java
import javax.swing.*;public class NativeOpenFileDialog { static { System.loadLibrary("natopndlg"); }; public static native void run (); public static void main (String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { NativeOpenFileDialog.run(); } }); }}
Here's NativeOpenFileDialog.m
#import <Cocoa/Cocoa.h>#include <jni.h>#include "NativeOpenFileDialog.h"JNIEXPORT void JNICALL Java_NativeOpenFileDialog_run (JNIEnv *thisEnv, jclass jcls) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSOpenPanel *panel = [NSOpenPanel openPanel]; [panel setCanChooseFiles:YES]; [panel setCanChooseDirectories:YES]; [panel setAllowsMultipleSelection:YES]; if ([panel runModal] != NSModalResponseOK) NSLog(@"User did not press OK"); [pool release];}
And here's the makefile (I'm using Xcode 15.2):
SDK = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdkOpen.class: Open.java NativeOpenFileDialog.java NativeOpenFileDialog.m javac -h . NativeOpenFileDialog.java javac Open.java gcc -dynamiclib -o libnatopndlg.dylib -framework Cocoa -isysroot $(SDK) -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/darwin -fobjc-exceptions -std=c99 NativeOpenFileDialog.m
$ java Open
That command raises this exception when the button is clicked:
NSInternalInconsistencyException', reason: 'NSWindow should only be instantiated on the main thread!
Which is understandable knowing that the panel is supposed to be opened on the UI thread.