由于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应用程序以相同的方式。
答案 0 :(得分:3)
事实证明,大约在5.5年后,这不是未来……iOS上没有JVM。
但是您绝对可以做到,即从Java调用Swift API。就是说,这很麻烦,因为AFAIK,您必须绕过C / C ++。
这是交易:
以下内容严重依赖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!