Reputation: 573
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.
Upvotes: 4
Views: 1868
Reputation: 3296
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.
Upvotes: 2
Reputation: 1661
I think this is not possible.
What you can do is write a c/c++-library with the code you want to share and use it in objective-c and java (via JNI). Anyway, you'll have to rewrite your code either to port it to java (where you'd have redundant sourcecode), or to remove your code from your objective-c project and create a c library which you can use in your objective-c and your java project.
Upvotes: 0