Can anyone please tell me how to call Objectice-C method from Java.
I heard about two techniques for that JNI and JNA.
There is a code written in Objective-C for IOS application and I want to use the code in Java project.
JNA is a library which can be used to access native methods. This is very practical if the rest of your application is written in Java because you can avoid writing any native code.
To interact with Objective-C, you would need to interact with the runtime library of Objective-C. Here is a very basic example.
// This method sets NSWindow.allowsAutomaticWindowTabbing to false.
// Note that it will terminate your application on macOS 10.11 and earlier as described below.
// https://developer.apple.com/documentation/appkit/nswindow/1646657-allowsautomaticwindowtabbing
void disableAutomaticWindowTabbing() {
Pointer classId = FoundationLibrary.INSTANCE.objc_getClass("NSWindow");
Pointer selector = FoundationLibrary.INSTANCE.sel_registerName("setAllowsAutomaticWindowTabbing:");
FoundationLibrary.INSTANCE.objc_msgSend(classId, selector, false);
}
// The interface of the runtime library of Objective-C.
interface FoundationLibrary extends Library {
FoundationLibrary INSTANCE = Native.load(
"Foundation",
FoundationLibrary.class,
Map.of(Library.OPTION_STRING_ENCODING, StandardCharsets.UTF_8.name()));
// https://developer.apple.com/documentation/objectivec/1418952-objc_getclass?language=objc
Pointer objc_getClass(String className);
// https://developer.apple.com/documentation/objectivec/1418557-sel_registername?language=objc
Pointer sel_registerName(String selectorName);
// https://developer.apple.com/documentation/objectivec/1456712-objc_msgsend?language=objc
// The return type is actually "generic". You might need to declare this function
// multiple times with different return types if you need them.
void objc_msgSend(Pointer receiver, Pointer selector, Object... args);
}
Note, however, that JNA cannot handle native exceptions. If objc_msgSend throws an exception, your application crashes immediately. Since setAllowsAutomaticWindowTabbing was not available before macOS 10.12, the example above would throw an exception and crash the application on macOS 10.11 and earlier.
With JNI, you need to write your own native code (i.e. with Objecttive-C++). For this reason, your project setup becomes more complex. However, it might be a good fit if you expect to write a major part of your logic in Objective-C anyway. Also note that the Objective-C compiler might catch some misusages of the API which can make the application more robust. In contrast to JNA, you are also able to handle native exceptions.
There is also JEP 389: Foreign Linker API (Incubator). I think it is an alternative to JNA but with native support by the JVM. Beside that, there are other libraries and tools which work on top of JNA or JNI to interact with Objective-C specifically.
The blog post Speaking Cocoa From Java from the author of Java-Objective-C-Bridge might also be an interesting read.
Rococoa facilitates using ObjectiveC code from Java.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With