写作&使用Java的JNI调用Swift代码

时间:2014-12-23 21:38:14

标签: java objective-c swift java-native-interface

由于see here,可以使用JVM的JNI从Java代码执行本机C / C ++方法调用。 但是如何执行Swift方法的调用?当Swift变得更受欢迎时,这是可能的还是可能的(可以在合理的时间范围内实现)?

我想访问Apple的本机API,只有在Objective-C或Swift中编写应用程序时才能访问它。由于JVM刚刚被移植到ARMv8(64位),我还可以将JVM想象为未来iOS应用程序的替代运行时。但是可能未来......现在是:JVM在Mac OS X上运行,可以在Swift中为Mac OS X编写应用程序,可以访问Java可能无法访问的某些API应用程序以相同的方式。

1 个答案:

答案 0 :(得分:3)

事实证明,大约在5.5年后,这不是未来……iOS上没有JVM。

但是您绝对可以做到,即从Java调用Swift API。就是说,这很麻烦,因为AFAIK,您必须绕过C / C ++。

这是交易:

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

以下内容严重依赖this question

代码

您的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 dylib,我们可以编译C dylib,它链接到Swift dylib:

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

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

等等!

从Java调用Swift!