从 Java 调用 Objective-C 方法

问题描述 投票:0回答:3

谁能告诉我如何从 Java 调用 Objectice-C 方法。

我听说过 JNI 和 JNA 两种技术。

有一段用 Objective-C 编写的 IOS 应用程序代码,我想在 Java 项目中使用该代码。

java objective-c java-native-interface jna
3个回答
2
投票

JNA(Java 本机访问)

JNA是一个可用于访问本机方法的库。如果应用程序的其余部分是用 Java 编写的,那么这非常实用,因为您可以避免编写任何本机代码。

要与 Objective-C 交互,您需要与 Objective-C 的 运行时库 交互。这是一个非常基本的例子。

// 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);
}

但是请注意,JNA 无法处理本机异常。如果

objc_msgSend
抛出异常,您的应用程序会立即崩溃。由于
setAllowsAutomaticWindowTabbing
在 macOS 10.12 之前不可用,因此上面的示例将引发异常并使应用程序在 macOS 10.11 及更早版本上崩溃。

JNI(Java 本机接口)

使用JNI,您需要编写自己的本机代码(即使用Objecttive-C++)。因此,您的项目设置变得更加复杂。然而,如果您希望用 Objective-C 编写逻辑的主要部分,那么它可能是一个不错的选择。另请注意,Objective-C 编译器可能会捕获 API 的一些误用,从而使应用程序更加健壮。与 JNA 相比,您还可以处理本机异常。

其他

还有JEP 389:外部链接器 API(孵化器)。我认为它是 JNA 的替代方案,但具有 JVM 的本机支持。除此之外,还有其他库和工具在 JNA 或 JNI 之上工作,专门与 Objective-C 交互。

来自 Java-Objective-C-Bridge 作者的博客文章 Speaking Cocoa From Java 也可能是一本有趣的读物。


1
投票

Rococoa 方便使用 Java 中的 ObjectiveC 代码。


0
投票

我认为这是不可能的。

您可以做的是使用您想要共享的代码编写一个 c/c++ 库,并在 Objective-C 和 Java 中使用它(通过 JNI)。 不管怎样,你必须重写你的代码,要么将它移植到java(在那里你会有多余的源代码),要么从你的objective-c项目中删除你的代码并创建一个可以在你的objective-c中使用的c库和你的 java 项目。

© www.soinside.com 2019 - 2024. All rights reserved.