この記事はkdnaktの1人 Advent Calendar 2020の6日目の記事です。
2020年は会社でKotlin dojoを主催して週1回30分Kotlinと戯れていました。12月はその集大成ということで、KotlinでHTTPサーバーを作ってみたいと思います。どこまでできるか、お楽しみ……。
[ソケット通信にチャレンジ]
5日目までで、Kotlin/NativeでHello worldするだけのシンプルなプロジェクトを作成しました。
これまでのところ、まったくHTTPサーバーらしいことができていませんので、今回は以下のスライドを参考に、ソケット通信にチャレンジしたいと思います。
KotlinからはJavaのクラスを利用できるはず、と考えて雑にjava.net.ServerSocketを作成する部分を実装してみます。Kotlinの変数宣言はvalでいけるからこうして……あれ?
コンパイルエラーが消えません。import文が追加されていないので当然ですが、コンパイルエラーを修正するためのquick fixで自動importができないようです。
自動でimportされないので、手動でimport文を追加します。コンパイルエラーはなくなったようです。ServerSocketクラスのコンストラクターも認識されているようだしこれで安心です。
早速gradle nativeBinaries
コマンドでビルドを実行してみます。
$ gradle nativeBinaries > Configure project : Kotlin Multiplatform Projects are an Alpha feature. See: https://kotlinlang.org/docs/reference/evolution/components-stability.html. To hide this message, add 'kotlin.mpp.stability.nowarn=true' to the Gradle properties. > Task :compileKotlinNative FAILED e: /Users/akito/Develop/sandbox/kttpd/src/nativeMain/kotlin/com/kdnakt/kttpd/hello.kt: (3, 8): Unresolved reference: java e: /Users/akito/Develop/sandbox/kttpd/src/nativeMain/kotlin/com/kdnakt/kttpd/hello.kt: (7, 16): Unresolved reference: ServerSocket FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':compileKotlinNative'. > Compilation finished with errors * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. * Get more help at https://help.gradle.org Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0. Use '--warning-mode all' to show the individual deprecation warnings. See https://docs.gradle.org/6.7.1/userguide/command_line_interface.html#sec:command_line_warnings BUILD FAILED in 26s 1 actionable task: 1 executed
例によって警告がいくつか出たな、などと考えていたらビルドが失敗してしまいました。Unresolved reference: java
という嫌な雰囲気のエラーメッセージが目に入りました。
[KotlinとKotlin/Native]
そういえば、KotlinとKotlin/Nativeって明らかに区別されてるよな、NativeだしJVM上で動くわけじゃないのにJavaの標準ライブラリをどうやって利用できるんだろう?と疑問に思いGoogle先生に質問すると、Stack Overflowにたどり着きました。
そこには予想通りの答えがありました。
You won't have access to Java packages in Kotlin Native.
(意訳:Kotlin NativeではJavaパッケージなんか使えません)
新しいプログラミング言語の学び方を参考に実装を進めていけば、KotlinとJavaは同じライブラリが使えるからなんとかなるだろう、という甘い考えで始めたプロジェクトです。しかし、初手でKotlin/Nativeを選択してしまったのが間違いだったようです。
Kotlin/NativeではJavaの標準ライブラリが利用できない以上、新しいプログラミング言語の学び方を参考に実装をすすめることは困難です。
KotlinとKotlin/Nativeは別物であり、自分がこのプロジェクトを通して学びたかったのはKotlin、しかしKotlin/NativeもKotlinと名がつく以上間違ってはいないはず……。
Kotlin/Nativeを捨てるべきかどうか迷いながら公式サイトを見ていると次のような説明がありました。
Kotlin/Native - Kotlin Programming Language
Kotlin/Native is a technology for compiling Kotlin code to native binaries, which can run without a virtual machine. It is an LLVM based backend for the Kotlin compiler and native implementation of the Kotlin standard library.
(意訳:Kotlin NativeはKotlinをネイティブバイナリにします、Kotlin標準ライブラリも使えます)
なんだかまだ戦えそうな気がしてきたので、Kotlin/Nativeで使えそうな標準ライブラリを探してみましたが、println()
関数ですら一部しかKotlin/Nativeで利用できず、ServerSocketなどのネットワーク通信関連のクラスはやはり利用できないようです。
kotlin.io - Kotlin Programming Language
諦めきれずに探していると、いくつか参考にできそうなサイトを見つけることができました。
Kotlin/Native POSIX Socket Server · GitHub
出てくるコードをみていると、alloc
やsockaddr_in
といった、ほぼC言語の世界です。ネイティブなので当然といえば当然な気もしますが……。
せっかくなので、このあたりのサイトを参考に実装を進めていきたいと思います。
ついでにC言語も勉強しよう……。
[まとめ]
- Kotlin/NativeではJava標準ライブラリを利用できない
- 代わりにPOSIXライブラリを利用して実装を進められそう