3

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

我听说了 JNI 和 JNA 的两种技术。

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

4

3 回答 3

1

Rococoa有助于使用 Java 中的 ObjectiveC 代码。

于 2012-12-05T14:38:40.490 回答
1

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抛出异常,您的应用程序会立即崩溃。上面的示例将引发异常并因此在 macOS 10.11 及更早版本上使应用程序崩溃,因为setAllowsAutomaticWindowTabbing在 macOS 10.12 之前不可用。

JNI(Java 本地接口)

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

其他

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

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

于 2021-05-07T09:08:32.160 回答
0

我认为这是不可能的。

您可以做的是使用您想要共享的代码编写 ac/c++-library,并在 Objective-c 和 java(通过 JNI)中使用它。无论如何,您必须重写您的代码以将其移植到 java(您将有多余的源代码),或者从您的 Objective-C 项目中删除您的代码并创建您可以在您的 Objective-C 中使用的 ac 库和你的java项目。

于 2012-12-05T09:17:00.023 回答