我试图在多平台项目中从Kotlin调用Swift / Objective-C代码。调用平台代码没有问题。但是,当我尝试调用某个库(或框架,因为我不是iOS开发人员而不确定如何正确调用它)时,它将失败。Docs指出,如果正确导出,可以调用Objective-C代码和Swift:
Kotlin / Native提供与Objective-C的双向互操作性。如果正确导入到构建中,则可以在Kotlin代码中使用Objective-C框架和库(默认情况下会导入系统框架)。请参阅Gradle插件文档中的“使用cinterop”。如果Swift库的API已通过@objc导出到Objective-C,则可以在Kotlin代码中使用它。尚不支持Pure Swift模块。
但这并没有说明如何正确导入它们。它仅指向gradle插件描述,该描述描述了gradle插件的旧版本。因此它对我不起作用。最后,我发现了某种可能是导入Objective-C代码的方式:
fromPreset(presets.iosX64, 'ios') {
compilations.main.outputKinds('FRAMEWORK')
compilations.main {
cinterops {
firebase {
def pods = '${System.getProperty("user.home")}/Projects/kmpp/iosApp/Pods/'
includeDirs '${pods}Firebase/CoreOnly/Sources',
'${pods}FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers'
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
生成运行不会失败,但是不会导入任何内容。我究竟做错了什么?是否可以完全导入这样的库?
UPD:
在这里,我找到了一个使用cinterop工具示例,如下所示:
cd samples/gitchurn
../../dist/bin/cinterop -def src/main/c_interop/libgit2.def \
-compilerOpts -I/usr/local/include -o libgit2
Run Code Online (Sandbox Code Playgroud)
看来cinterop工具应该/dist/bin/在我的项目的文件夹中,但是没有这样的文件夹。我在哪里可以获得cinterop工具?
我的目标是编写一个Kotlin库,将其编译为WebAssembly并从JS调用其功能。几个小时以来,我一直在努力建立一个简单的问候世界。关于此主题的文档不存在或隐藏得很好。
这是我的kotlin文件:
@Used
public fun hello() {
println("Hello world!")
}
fun main(args: Array<String>) {
println("main() function executed!")
}
Run Code Online (Sandbox Code Playgroud)
当我将其编译为WebAssembly时,会得到一个hello.wasm和hello.wasm.js文件。
首先,我尝试使用如下代码来执行该功能:
WebAssembly.instantiateStreaming(fetch('hello.wasm'), importObject)
.then(obj => obj.instance.exports.hello());
Run Code Online (Sandbox Code Playgroud)
然后,我了解到需要在importObject参数中传递来自hello.wasm.js文件的导入。所以我想我需要使用hello.wasm.js文件正确初始化wasm程序。
当像下面那样加载wasm时,没有任何错误,并且执行了main()函数。
<script wasm="hello.wasm" src="hello.wasm.js"></script>
Run Code Online (Sandbox Code Playgroud)
但是,如何从JavaScript 执行hello()函数呢?我发现的唯一Kotlin wasm示例不是调用特定函数,而是从main()函数渲染某些内容。
此外,非常感谢与相关文档的任何链接。
更新: 我设法执行了该函数,但是我不相信这是正确的方法:
<script wasm="hello.wasm" src="hello.wasm.js"></script>
<script>
WebAssembly.instantiateStreaming(fetch('hello.wasm'), konan_dependencies)
.then(obj => obj.instance.exports['kfun:hello$$ValueType']());
</script>
Run Code Online (Sandbox Code Playgroud)
问题是,如果我这样做,我的wasm文件将被提取两次。
仅加载没有wasm属性的hello.wasm.js文件会给我以下错误:
Uncaught Error: Could not find the wasm attribute pointing to the WebAssembly binary.
at …Run Code Online (Sandbox Code Playgroud) javascript kotlin webassembly kotlin-js-interop kotlin-native
与 Kotlin 多平台项目抗争 我已经结束了与 Kotlin Native一起工作时需要NsData在我的 iOS 平台上工作的问题sharedModule。
因此,我需要将objectiveC 转换NsData为KotlinByteArray并返回。我怎样才能做到这一点?
我想在 Kotlin Native 中创建一个使用 REST API 公开 Web 服务器的应用程序,但我找不到任何最近的项目或库。有kwang但它似乎不再维护,它依赖于另一个 C 库。
我正在尝试实现一个观察者,以更改 UserDefaults 中给定键的值,该值来自用 Kotlin/Native 编写的多平台项目的 ios 本机部分。这是我写的代码:
fun subscribeForDataChange(storeName: String, callback: () -> Unit) {
NSUserDefaults(storeName).addObserver(
object : NSObject() {
fun observeValue(
observer: NSObject,
forKeyPath: String,
options: NSKeyValueObservingOptions,
context: COpaquePointer?
) {
callback()
print("Data Changed!!!")
}
},
options = NSKeyValueObservingOptionNew,
forKeyPath = DATA_KEY,
context = null
)
}
Run Code Online (Sandbox Code Playgroud)
问题是我从来没有收到通知,很可能是因为observeValueNSObject 中没有定义,但是我还应该做什么才能实现这一点?
我正在玩kotlin原生样本.我想知道如何String从pinnedByteArray 获得.只想在控制台中打印它.
我正在尝试通过 bash 执行命令,例如konanc.
在 KotlinJVM 中,这只是使用Runtime.getRuntime().exec("...")或创建Process使用ProcessBuilder,但是,这些类在 Kotlin-Native 中都不可用,因为它们是 Java 库的一部分。
我尝试在文档和 kotlin 原生 GitHub 存储库中搜索示例代码,但没有找到任何内容。
我正在尝试为我的 Kotlin/Native 项目提供支持ktor(kotlinx确切地说serialization)coroutines。所有库都适用于该项目的 Android 版本,但是当我尝试编译 Xcode 项目时,我收到错误消息,指出找不到kotlinx.serialization和库:kotlinx.coroutines
src/commonMain/kotlin/.../.kt:4:16: error: unresolved reference: coroutines
import kotlinx.coroutines.CoroutineDispatcher
^
src/commonMain/kotlin/.../.kt:5:16: error: unresolved reference: serialization
import kotlinx.serialization.json.JSON
Run Code Online (Sandbox Code Playgroud)
这是我的项目的 gradle 文件:
plugins {
id 'kotlin-multiplatform' version '1.3.11'
id 'kotlinx-serialization' version '1.3.0'
}
ext {
ktor_version = '1.0.1'
kotlinx_version = '1.1.0'
}
repositories {
maven { url "https://kotlin.bintray.com/ktor" }
maven { url "https://kotlin.bintray.com/kotlinx" }
google()
jcenter()
mavenCentral()
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android-extensions'
configurations { …Run Code Online (Sandbox Code Playgroud) Kotlin / Native的官方文档指出Kotlin / Native
..是Kotlin编译器基于LLVM的后端。
据我所理解:
因此,Kotlin / Native是否将Java字节码转换为LLVM IR?如果是这样,声明Kotlin / Native是LLVM后端是否正确?Kotlin代码是否可以编译到LLVM IR中?如果不是,那么每个编译步骤的输入和输出是什么?(例如:Kotlin-(kotlinc)-> Java字节码-(LLVM后端->本机二进制)
这篇博客文章指出Kotlin前端编译器(我认为它是指kotlinc)产生了我从未读过的Kotlin IR。
Kotlin编译器只有一个前端,但有多个后端,具体取决于您用来构建代码的插件。Kotlin / Native插件将Kotlin中间表示(IR)转换为本机代码(即,机器可执行的代码)。
这个报价正确吗?
它告诉您Java字节码,本机代码和JavaScript的编译过程相同。您编译Kotlin代码,然后有3个后端编译器提供预期的输出格式(Java字节码,JavaScript,二进制代码)。
最终平台特定的二进制文件是否包含本地Kotlin标准库,或者它是动态链接的?
我正在针对 iOS 的 Kotlin 多平台项目中研究 AES256 加密算法。
我检查了一些在纯 Kotlin 中实现这一点的现有库(例如krypto),但它们都不符合我对其余代码的要求(它们已经在 JVM 和 JS 中实现,因此无法更改) .
来自 iOS 背景,我决定使用CommonCrypto. 我从这里改编并移植了代码,但我坚持如何ULong通过引用传递CCCrypt函数并稍后检索其值。
我非常仔细地阅读了关于C Interop和Objective-C Interop的 Kotlin 文档,但我找不到任何可以解释如何处理我的案例的示例。
特别是,我的问题是numBytesEncrypted变量(见下面的代码)。我需要通过引用CCCrypt函数来传递它,然后读取它的值以NSData使用正确的长度实例化结果。在 Objective-C/Swift 中,我会&在调用函数时为变量加上前缀。
但是,Kotlin 不支持&运算符。如果我从文档中理解正确,那么 Native 中的替换是CValueRef( docs ),所以我使用cValue速记来获取正确类型的引用(应该是size_t,又名。ULong)。
我试图以CValueRef两种方式实例化,就类型检查而言,这两种方式似乎都有效:
val numBytesEncrypted = cValue<ULongVar>()
// or
val numBytesEncrypted = cValue<ULongVarOf<size_t>>()
Run Code Online (Sandbox Code Playgroud)
然后我使用这段代码来获取函数执行后的值: …
kotlin-native ×10
kotlin ×9
ios ×3
commoncrypto ×1
exec ×1
javascript ×1
shellexecute ×1
webassembly ×1