使用Java的JNI编写和调用Swift代码

Ale*_*lex 5 java java-native-interface objective-c swift

如您所见,由于JVM的JNI,人们可以从Java代码执行本机C / C ++方法调用。但是执行Swift方法的调用又如何呢?随着Swift的流行,这是否可能或将是可能的(可以在合理的时间范围内实施)?

我想访问Apple的本机API,该API仅在使用Objective-C或Swift编写应用程序时才可访问。由于JVM仅被移植到ARMv8(64位)上,因此我还可以想象JVM将在将来作为iOS应用程序的替代运行时。但这可能是未来。现在是:JVM运行在Mac OS X上,并且可以在Swift中为Mac OS X编写应用程序,这些应用程序可以访问Java应用程序无法访问的某些API。

hen*_*rik 8

好吧,大约 5\xc2\xbd 年后,事实证明,这不是未来……iOS 上没有 JVM。

\n

但你绝对可以做到,即从 Java 调用 Swift API。也就是说,这相当麻烦,因为据我所知,你必须绕道通过 C/C++。

\n

这是交易:

\n
    \n
  • 如您所知,您可以使用 JNI 来调用 C 代码。
  • \n
  • 您可以从 C 调用 Swift。
  • \n
\n

以下内容很大程度上依赖于这个问题

\n

代码

\n

您的 Java 代码位于helloworld/SwiftHelloWorld.java

\n
package helloworld;\n\npublic class SwiftHelloWorld {\n\n    static {\n        System.loadLibrary("SwiftHelloWorld");\n    }\n\n    public static native void printHelloWorldImpl();\n\n    public static void main(final String[] args) {\n        printHelloWorldImpl();\n    }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n

现在编写本机 C 代码(文件helloworld_SwiftHelloWorld.c):

\n
#include <jni.h>\n#include <stdio.h>\n#include "helloworld_SwiftHelloWorld.h"\n#include "helloworld_SwiftHelloWorld_swift.h"\n\nJNIEXPORT void JNICALL Java_helloworld_SwiftHelloWorld_printHelloWorldImpl\n  (JNIEnv *env, jclass clazz) {\n\n    int result = swiftHelloWorld(42);\n    printf("%s%i%s", "Hello World from JNI! ", result, "\\n");\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n

helloworld_SwiftHelloWorld_swift.h它使用一个以我们(尚未编写的)Swift 代码命名的头文件:

\n
int swiftHelloWorld(int);\n
Run Code Online (Sandbox Code Playgroud)\n

最后,我们的 Swift 代码位于SwiftCode.swift

\n
import Foundation\n\n// force the function to have a name callable by the c code\n@_silgen_name("swiftHelloWorld")\npublic func swiftHelloWorld(number: Int) -> Int {\n    print("Hello world from Swift: \\(number)")\n    return 69\n}\n
Run Code Online (Sandbox Code Playgroud)\n

建筑

\n

为了构建这一切,我们首先必须将 Swift 代码编译为动态库:

\n
swiftc SwiftCode.swift -emit-library -o libSwiftCode.dylib -Xlinker -install_name -Xlinker libSwiftCode.dylib\n
Run Code Online (Sandbox Code Playgroud)\n

我们使用-Xlinker指令来确保 dylib 的位置是相对的。

\n

在创建 C dylib 之前,我们首先必须生成 Java 头文件:

\n
javac -h . helloworld/SwiftHelloWorld.java\n
Run Code Online (Sandbox Code Playgroud)\n

现在我们有了 Java 头文件和 Swift dylib,我们可以编译 C dylib,它链接到 Swift dylib:

\n
gcc -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin/" -o libSwiftHelloWorld.dylib -dynamiclib helloworld_SwiftHelloWorld.c libSwiftCode.dylib\n
Run Code Online (Sandbox Code Playgroud)\n

现在一切都已就绪,我们必须确保两个 dylib 位于同一目录中,并且 Java 可以找到该目录,即您可能需要设置-Djava.library.path=<dir of your dylibs>.

\n

等瞧\xc3\xa0!

\n

Swift 从 Java 调用!

\n