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

10

正如您在这里看到的那样,由于JVM的JNI,可以从Java代码中执行本机C / C ++方法调用。但是,如何调用Swift方法呢?这可能吗或者将来可能实现(可以在合理的时间范围内实现)随着Swift变得越来越流行?

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


我非常确定RoboVM的团队会对此采取行动... - Samuel Audet
可能是使用Swift在iOS和Android之间共享核心代码的重复问题。 - Paul Sweatte
1个回答

7

大约5年半后,结果证明它并不是未来...iOS上没有JVM。

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

以下是解决方案:

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

以下内容主要参考这个问题

代码

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

package helloworld;

public class SwiftHelloWorld {

    static {
        System.loadLibrary("SwiftHelloWorld");
    }

    public static native void printHelloWorldImpl();

    public static void main(final String[] args) {
        printHelloWorldImpl();
    }

}

现在编写本地C代码(文件helloworld_SwiftHelloWorld.c):
#include <jni.h>
#include <stdio.h>
#include "helloworld_SwiftHelloWorld.h"
#include "helloworld_SwiftHelloWorld_swift.h"

JNIEXPORT void JNICALL Java_helloworld_SwiftHelloWorld_printHelloWorldImpl
  (JNIEnv *env, jclass clazz) {

    int result = swiftHelloWorld(42);
    printf("%s%i%s", "Hello World from JNI! ", result, "\n");

}

这里使用一个名为 helloworld_SwiftHelloWorld_swift.h 的头文件来引用我们尚未编写的 Swift 代码:

int swiftHelloWorld(int);

最后,我们的Swift代码存储在SwiftCode.swift中:

import Foundation

// force the function to have a name callable by the c code
@_silgen_name("swiftHelloWorld")
public func swiftHelloWorld(number: Int) -> Int {
    print("Hello world from Swift: \(number)")
    return 69
}

构建

要构建所有这些,我们首先必须将Swift代码编译为动态库:

swiftc SwiftCode.swift -emit-library -o libSwiftCode.dylib -Xlinker -install_name -Xlinker libSwiftCode.dylib

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

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

javac -h . helloworld/SwiftHelloWorld.java

现在我们有了Java头文件和Swift动态库,我们可以编译C动态库,并将其链接到Swift动态库:

gcc -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin/" -o libSwiftHelloWorld.dylib -dynamiclib helloworld_SwiftHelloWorld.c libSwiftCode.dylib

现在一切就绪,我们必须确保两个dylibs在同一个目录下,并且该目录可以被Java找到,即您可能需要设置-Djava.library.path=<dir of your dylibs>
Et voilà!
从Java调用了Swift!

1
生成Java >= 9头文件的命令是:javac -h . helloworld/SwiftHelloWorld.java资源:https://dev59.com/Z2gu5IYBdhLWcg3wdGwb - Anton Petrov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接