Medley Developer Blog

株式会社メドレーのエンジニア・デザイナーによるブログです

Kotlin/Native を検証してみた

こんにちは、インキュベーション本部でエンジニアをしています世嘉良です。

インキュベーション本部は2020年2月から新規事業の開拓などを目的に新設されたのですが、その中でも若手の部類として日々頑張っています。 CTO 平山のインタビューとともにインキュベーションチームの紹介記事が、コーポレートサイトに掲載されています。こちらもぜひご覧ください。 https://www.medley.jp/team/creator-story-incubation.html

さて、今回は社内で行っている勉強会:テックランチの中で「Kotlin/Native」について発表する機会があったので紹介させていただきます。

Kotlin/Native について

Kotlin は JetBrains 社によって 2011 年に発表されたプログラミング言語です。

現在では Android 開発などで主流の言語となっており、多くの人に利用されていると思います。 Kotlin/Native とはそんな Kotlin を使って様々なプラットフォーム上で実行可能なファイルを生成しようというプロジェクトです。

Kotlin/Native - Kotlin Programming Language

仕組みとしては Kotlin のコードをもとに LLVM を生成し、それを様々なプラットフォームで利用可能なネイティブバイナリにコンパイルすることで追加のランタイムや JVM なしで動作するようにしています。

サポートしているプラットフォームは下記のとおりです。

コードの共通化について

Kotlin/Native のチュートリアルを参考に、Android / iOS で共通化の流れを追ってみます。

作成されるプロジェクトは Android / iOS でそれぞれ "Hello, World!" を出力するシンプルなプログラムです。

Kotlin Playground: Edit, Run, Share Kotlin Code Online

通常のプロジェクトとは別に SharedCode というプロジェクトを作成し、この中に Kotlin/Native (Android / iOS 共通のコード) を記述していきます。 それぞれのコードのレイアウトは以下の通りです。 ※ SharedCode を読み込むためのマルチプラットフォームのための gradle ファイルも必要で、先程のウェブサイトに記載されています。

f:id:medley_inc:20200508170713p:plain

commonMain の中に 「expect」 というキーワードを使って抽象型のようなものを宣言し、 androidMain / iOSMain といった各プラットフォームの実装の中で 「actual」 というキーワードを使用してその内容を記述します。

// commonMain
expect fun platformName(): String

// androidMain
actual fun platformName(): String {
    return "Android"
}

// iOSMain
actual fun platformName(): String {
    return UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion
}

このチュートリアルには記載ありませんが、「expect」 というキーワードはクラスや関数・アノテーションといったすべてのものに定義することができます。

Platform-Specific Declarations - Kotlin Programming Language

また iOSMain 内であれば iOS の Foundation フレームワークといったように、各プラットフォームごとのフレームワークもそれぞれ利用することができます。

こうしてできた、SharedCode のライブラリは Android/iOS のプロジェクトから使い慣れたライブラリと同じようにインポートすることができます。

f:id:medley_inc:20200508170931p:plain

f:id:medley_inc:20200508170949p:plain

f:id:medley_inc:20200508171007p:plain

Kotlin/Native の制約について

JVM 上で Kotlin を動かしていた時には標準ライブラリやメモリ管理には Java の資産を利用することができましたが、Kotlin/Native ではそれを利用することができないという制約があります。

具体的にアプリを作成する際には下記の点に注意が必要でした。

  • Java の標準ライブラリを使用しているライブラリを利用できないため Kotlin で記述されたライブラリのみが使用する
  • iOS アプリを開発する際には memScope, alloc / free などを利用してメモリ管理を自分で行う必要がある

Java の資産が利用できない Kotlin に対して心配することもありましたが、Kotlin/Native 向けに様々なライブラリが 提供されておりそれらを利用することで問題を解決しました。

f:id:medley_inc:20200508171035p:plain

現状は日付管理ですらサードパーティ製のライブラリで操作する必要があるのが不満ですが、Kotlin/Native の発展によってこういった不便さは解決されるように願っています。

  • 「suspend」 関数を iOS 側から直接呼び出すことができない (コールバック関数やなどに変換して呼び出す必要がある)
  • Kotlin で定義した宣言や型の一部が Swift だと別名になっている (「 objc_runtime_name」 や 「swift_name」 を参照する必要がある)
  • 「companion object」 や 「object」 などシングルトンの宣言に対してオブジェクトをフリーズするか 「ThreadLocal / SharedImmutable」 のアノテーションを付与する必要がある

こちらは iOS で利用する場合の注意ですが、いくつかの Kotlin の機能が利用できなかったり、追加の記述が必要なものがあります。 詳しくは下記の資料を参照ください。

Kotlin/Native as an Apple Framework - Kotlin Programming Language

kotlin-native/IMMUTABILITY.md

Kotlin/Native の利用例

まだまだ利用例が少ないため参考になる資料などがあまりないのですが、以下の実装がオープンソースとして公開されているため構成や雰囲気を掴むためにはちょうど良い資料となりました。

まとめ

弊社では 「CLINICS」 というオンライン診察を行うことができるアプリをリリースしています。

CLINICS を長期的に運用していくための技術調査の一環として、近年の Android 界隈で話題にあがっていた「Kotlin/Native」について検証し発表してみました。

まだまだ発展途上感のある技術ですが、実用性のあるプロジェクトだと思いますのでご興味のある方はぜひ一度お試しください!