这个坑还是比较有意思的,主要来说分为以下几种情况:
- 编译时报
io.ktor
不存在; - 编译时报
编译器版本不对
; - 编译时报
curl/lib 找不到
; - 编译时报
_iconv 函数找不到
。
总共这四种情况,我们一个个来解决。
先说一个前提条件,gradle
必须用 5.4
以上版本,切记!
一、io.ktor
不存在
首先必须确保引用是对的,在 Kotlin/Native 内,引用往往是分段的,如果认为 commonMain
里加了依赖就可以延伸到全部的 Target,这就大错特错了。正确的引用方法是,在 commonMain
里引用 metadata
,而在 Target 内引用平台专属的包,如下所示:
sourceSets {
commonMain {
dependencies {
implementation kotlin('stdlib-common')
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.2.1'
implementation 'io.ktor:ktor-client-core:1.2.0'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.11.0'
}
}
macosMain {
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.2.1'
implementation 'io.ktor:ktor-client-curl:1.2.0'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:0.11.0'
}
}
}
其中的对应关系一眼就能看出来,在 commonMain
中引用 ktor-client-core
,而在 macosMain
内必须引用 ktor-client-curl
才能够完成编译。还记得之前说的 expect
和 actual
吗?这里的依赖原理与它是一致的。
二、编译器版本不对
这个问题是非常大的坑,要解决这个问题,唯一的办法就是把所有的库升级到最新,之前我用 Kotlin 1.3.21
,在编译协程库时,就必须对应用 1.1.1
的协程库,然而加入了 ktor-client
后,却发现 ktor-client
不论用哪个版本,都无法与 kotlin 1.3.21
和 Coroutines 1.1.1
完全对应起来,永远都会编译报版本兼容异常。
所以在这种情况下只能升级,把一切都升到最高版本,使用以下命令可以升级 Kotlin
编译器:
$ brew upgrade kotlin
安装完成后,需要确认当前的 Kotlin 编译器版本:
$ kotlin -version
Kotlin version 1.3.31-release-197 (JRE 1.8.0_202-b08)
$ konanc -version
info: kotlinc-native 1.3.31 (JRE 1.8.0_202-b08)
Kotlin/Native: 1.2.1
这两个命令的版本同时正确才可以,不然的话,依然需要进行升级。
升级完毕后,使用以下版本号可以顺利的完成编译:
Kotlin: 1.3.31
Coroutines: 1.2.1
Ktor-Client: 1.2.0
Serialization: 0.11.0
三、curl/lib
找不到
这个问题很好解决,只需要安装 curl
的 library 即可解决,一个命令搞定:
$ brew install curl curl-openssl
安装后在 /usr/local/opt/curl/lib
就会出现链接时需要的库。
四、_iconv
找不到
最后的这个问题,说难不难,说简单也不简单,或许是因为我对 gradle 不熟悉吧,搜了很多资料才知道可以手动添加 link 依赖,写法如下:
macosX64("macos") {
binaries {
executable {
linkerOpts "-L/usr/lib -liconv"
entryPoint 'main'
}
}
}
这样就可以成功的链接到 iconv 了。在这里多提一句,不要用 brew 安装出来的 iconv,这里面的导出函数名称不对,是故意与系统自带的进行区分的,如果你用了那个库,依然会发现链接失败。
好了,使用 Ktor-Client 的所有问题都解决了,现在可以写点代码来看看成果,我们尝试用 Ktor-Client 来发起请求,并对返回的 json 字符串作出解析。
先用 ktor
实现一个简单的服务端程序,如果你还不会 ktor,可以参考我写的《Ktor 从入门到放弃》系列。
fun Routing.sampletRouting() {
get("/hello") {
call.respondText{ "{\"result\": \"callback from server\", \"uuid\":\"${localSession.uuid}\"}" }
}
}
跑起服务器后,用浏览器访问 http://0.0.0.0/hello
进行验证:
{"result": "callback from server", "uuid":"fba4a6c8-8802-4ff2-b883-78e85a695110"}
然后写一个简单的请求就好了,需要注意的是,Ktor-Client 是运行在协程内的,所以我们同样需要用协程来调用它:
import io.ktor.client.HttpClient
import io.ktor.client.request.get
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.*
import kotlinx.serialization.json.Json
@Serializable
data class Data(val result: String, val uuid: String)
fun main(args: Array<String>) = runBlocking {
val client = HttpClient()
val ret = client.get<String>("http://0.0.0.0/hello") { }
val obj = Json.parse(Data.serializer(), ret)
println(obj)
}
网友评论