Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Starting Kotlin/Native おなじところ、ちがうところ #m3kt

Starting Kotlin/Native おなじところ、ちがうところ #m3kt

2017/08/24 どこでもKotlin #1 @Cloud Works
エムスリー株式会社 星川貴樹 (@oboenikui)

Takaki Hoshikawa

August 24, 2017
Tweet

More Decks by Takaki Hoshikawa

Other Decks in Technology

Transcript

  1. 2017/08/24 どこでもKotlin #m3kt
    Starting Kotlin/Native
    おなじところ、ちがうところ
    2017/08/24 どこでもKotlin #1 @Crowd Works
    エムスリー株式会社
    星川貴樹 (@oboenikui)

    View Slide

  2. 2017/08/24 どこでもKotlin #m3kt
    目次
    1. Kotlin/Nativeとは?
    a. LLVMとは?
    b. できること・できないこと
    2. Kotlin/Nativeを使い始める
    3. おなじところ、ちがうところ
    4. 使ってみた

    View Slide

  3. 2017/08/24 どこでもKotlin #m3kt
    自己紹介
    ● 星川 貴樹 (@oboenikui)
    ● 17卒の入社5ヶ月目
    ● 現在の仕事は主にAndroidアプリ
    ● 野球(見る方)、CTFが趣味

    View Slide

  4. 2017/08/24 どこでもKotlin #m3kt
    Kotlin/Nativeとは?
    ● KotlinコードをLLVM経由で各ターゲット向けネイティ
    ブバイナリにコンパイルするコンパイラ
    ● 今年4月公開,現在v0.3 (まだ実用レベルにない)
    ● 現在サポートが確認されているターゲット
    ○ x86-64系
    Linux, macOS, Windows
    ○ ARM系
    iOS, Android, Raspberry Pi
    ○ その他
    (WebAssembly)

    View Slide

  5. 2017/08/24 どこでもKotlin #m3kt
    LLVMとは?
    中間言語を介して様々なターゲット向けのバイナリにコンパイルする
    LLVM
    bitcode

    View Slide

  6. 2017/08/24 どこでもKotlin #m3kt
    LLVMとは?
    中間言語を介して様々なターゲット向けのバイナリにコンパイルする
    LLVM
    bitcode

    View Slide

  7. 2017/08/24 どこでもKotlin #m3kt
    できること・できないこと
    ● ˉできるˉ
    ○ kotlin.*パッケージに含まれるクラス・メソッドを使う
    ○ Cのヘッダーファイルが使えるライブラリを使う
    ○ デバッグ
    ● ˈできないˈ
    ○ Fileクラスのようにkotlin.*パッケージに含まれないJavaの
    クラスを使う
    ○ Javaのライブラリを使う
    ○ Cのヘッダーファイルを含まないライブラリを使う※

    View Slide

  8. 2017/08/24 どこでもKotlin #m3kt
    Kotlin/Nativeを使い始める
    1. GitHubからクローン
    $ git clone https://github.com/jetbrains/kotlin-native
    2. JetBrainsのサイトからダウンロード
    (サンプルを試す場合はこれがおすすめ)
    Download from
    https://blog.jetbrains.com/kotlin/2017/06/kotlinnative-v0-3-is-out/

    View Slide

  9. 2017/08/24 どこでもKotlin #m3kt
    Kotlin/Nativeを使い始める
    3. Gradleで導入 (IDEAでも一応コーディング可)
    apply plugin: 'konan'
    buildscript {
    repositories {
    mavenCentral()
    maven {
    url "https://dl.bintray.com/jetbrains/kotlin-native-dependencies"
    }
    }
    dependencies {
    classpath "org.jetbrains.kotlin:kotlin-native-gradle-plugin:+"
    }
    }

    View Slide

  10. 2017/08/24 どこでもKotlin #m3kt
    Kotlin/Nativeのコンパイルフロー
    .def
    使用するヘッダー
    ファイルを記述
    .c
    .h
    Source
    cinterop
    konanc
    .bc
    .bc
    .kexe
    Shared
    Library
    LLVM bitcode

    View Slide

  11. 2017/08/24 どこでもKotlin #m3kt
    Cのメソッドの呼び出され方
    ● CのヘッダーファイルからKotlinとCのコードを生成

    // stdio.kt
    fun printf(arg0: String?, vararg args: Any?): Int =
    memScoped {
    // kni_printfの返り値(関数ポインタ)の実行処理
    ...
    }
    @SymbolName("stdio_kni_printf")
    private external fun kni_printf(): NativePtr
    // stdiostubs.c
    void* stdio_kni_printf() { return printf; }

    View Slide

  12. 2017/08/24 どこでもKotlin #m3kt
    Cのメソッドの呼び出され方
    ● CのヘッダーファイルからKotlinとCのコードを生成

    // stdio.kt
    fun printf(arg0: String?, vararg args: Any?): Int =
    memScoped {
    // kni_printfの返り値(関数ポインタ)の実行処理
    ...
    }
    @SymbolName("stdio_kni_printf")
    private external fun kni_printf(): NativePtr
    // stdiostubs.c
    void* stdio_kni_printf() { return printf; }
    Kotlin/JSの外部ライブラリ呼び出しの記法と同じ

    View Slide

  13. 2017/08/24 どこでもKotlin #m3kt
    C++のライブラリは使えない?
    ● 現状ヘッダファイルからKotlinコードを生成できないた
    め、人の手で実装する必要あり
    ● ニーズもあると思うのでそのうち実装されてほしい

    View Slide

  14. 2017/08/24 どこでもKotlin #m3kt
    おなじところ、ちがうところ

    View Slide

  15. 2017/08/24 どこでもKotlin #m3kt
    Kotlin/JVMと基本的に同じところ
    ● kotlin.*パッケージのクラスは使用可能
    (最終的には全て実装されるはず)
    ● ほとんどの文法

    View Slide

  16. 2017/08/24 どこでもKotlin #m3kt
    Kotlin/JVMと基本的に同じところ
    ● kotlin.*パッケージのクラスは使用可能
    (最終的には全て実装されるはず)
    ● ほとんどの文法
    ➔ 完全にKotlinの世界に収まっているライブラリは
    理論上JVMでもNativeでも利用可能に!

    View Slide

  17. 2017/08/24 どこでもKotlin #m3kt
    Kotlin/JVMとの大きな違い
    ● 使えるライブラリの違い
    ● Cのための相互運用型・メソッド
    ● メモリ管理
    ● プラットフォーム型がない
    ● 安全性

    View Slide

  18. 2017/08/24 どこでもKotlin #m3kt
    Cのための相互運用型・メソッド
    ● signed, unsignedな整数・浮動小数点型の数値は、同じ幅の数値型に
    マップ (32bit幅の整数の場合unsignedでもInt)
    ● ポインタ・配列はCPointer?にマップ
    ● enumはenumか整数値にマップ
    ● 構造体はCStructVarを継承したクラスにマップ
    ● typedefはtypealiasにマップ
    ● C相互運用のための拡張関数が定義されている など
    (例)
    char *getenv(const char *)
    Kotlin
    fun getenv(arg0: String?): CPointer?
    Kotlin
    C

    View Slide

  19. 2017/08/24 どこでもKotlin #m3kt
    Cのための相互運用型・メソッド
    ● signed, unsignedな整数・浮動小数点型の数値は、同じ幅の数値型に
    マップ (32bit幅の整数の場合unsignedでもInt)
    ● ポインタ・配列はCPointer?にマップ
    ● enumはenumか整数値にマップ
    ● 構造体はCStructVarを継承したクラスにマップ
    ● typedefはtypealiasにマップ
    ● C相互運用のための拡張関数が定義されている など
    (例)
    // kotlinx.cinterop.Utils
    fun CPointer.toKString(): String
    fun getenv(arg0: String?): CPointer?
    Kotlin

    View Slide

  20. 2017/08/24 どこでもKotlin #m3kt
    Cのための相互運用型・メソッド
    ● signed, unsignedな整数・浮動小数点型の数値は、同じ幅の数値型に
    マップ (32bit幅の整数の場合unsignedでもInt)
    ● ポインタ・配列はCPointer?にマップ
    ● enumはenumか整数値にマップ
    ● 構造体はCStructVarを継承したクラスにマップ
    ● typedefはtypealiasにマップ
    ● C相互運用のための拡張関数が定義されている など
    (例)
    val path = getenv("PATH")?.toKString() ?: ""

    View Slide

  21. 2017/08/24 どこでもKotlin #m3kt
    メモリ管理
    Kotlinのクラス
    ● 現在の構想では、ターゲットによって最適なメモリ管理
    方法を選択できるようにする予定
    ● 例えば、GC、手動管理、ARC(iOS)、といった選択が可
    能に

    View Slide

  22. 2017/08/24 どこでもKotlin #m3kt
    メモリ管理
    Cとの相互運用部分
    val buffer = nativeHeap.allocArray(64 * 1024)
    fgets(buffer, bufferLength, file)?.toKString() ?: ""
    ...
    nativeHeap.free(buffer)

    View Slide

  23. 2017/08/24 どこでもKotlin #m3kt
    メモリ管理
    Cとの相互運用部分
    memScoped {
    val bufferLength = 64 * 1024
    val buffer = allocArray(bufferLength)
    for (i in 1..count) {
    val nextLine = fgets(buffer, bufferLength, file)?
    .toKString()
    ...
    }
    }

    View Slide

  24. 2017/08/24 どこでもKotlin #m3kt
    メモリ管理
    Cとの相互運用部分
    memScoped {
    val bufferLength = 64 * 1024
    val buffer = allocArray(bufferLength)
    for (i in 1..count) {
    val nextLine = fgets(buffer, bufferLength, file)?
    .toKString()
    ...
    }
    }
    動的確保した部分はmemScopedを抜
    けると自動的にfreeされる

    View Slide

  25. 2017/08/24 どこでもKotlin #m3kt
    メモリ管理
    Cとの相互運用部分
    val head = memScoped {
    val bufferLength = 64 * 1024
    val buffer = allocArray(bufferLength)
    fgets(buffer, bufferLength, file)?
    .toKString() ?: ""
    }

    View Slide

  26. 2017/08/24 どこでもKotlin #m3kt
    メモリ管理
    Cとの相互運用部分
    val head = memScoped {
    val bufferLength = 64 * 1024
    val buffer = allocArray(bufferLength)
    fgets(buffer, bufferLength, file)?
    .toKString() ?: ""
    }

    View Slide

  27. 2017/08/24 どこでもKotlin #m3kt
    プラットフォーム型がない
    ● Javaが介さないためプラットフォーム型は存在しない!!
    ● Cでポインタを返すメソッドはKotlinでは全て
    CPointer?を返す!!

    View Slide

  28. 2017/08/24 どこでもKotlin #m3kt
    プラットフォーム型がない
    ● Javaが介さないためプラットフォーム型は存在しない!!
    ● Cでポインタを返すメソッドはKotlinでは全て
    CPointer?を返す!!
    ➔ その結果サンプルコードは!!演算子だらけになってし
    まっている!!

    View Slide

  29. 2017/08/24 どこでもKotlin #m3kt

    View Slide

  30. 2017/08/24 どこでもKotlin #m3kt
    安全性
    ● Kotlin部分は領域外アクセスなどに対し比較的安全だが、C相
    互運用部分は注意が必要
    val arr = arrayOf(1, 2, 3)
    for(i in 0..3)
    println(arr[i])
    memScoped {
    val arr = intArrayOf(1, 2, 3)
    .toCValues()
    .getPointer(this)
    for (i in 0..3)
    println(arr[i])
    }

    View Slide

  31. 2017/08/24 どこでもKotlin #m3kt
    安全性
    ● Kotlin部分は領域外アクセスなどに対し比較的安全だが、C相
    互運用部分は注意が必要
    val arr = arrayOf(1, 2, 3)
    for(i in 0..3)
    println(arr[i])
    memScoped {
    val arr = intArrayOf(1, 2, 3)
    .toCValues()
    .getPointer(this)
    for (i in 0..3)
    println(arr[i])
    }
    1
    2
    3
    268435456
    kotlin.ArrayIndexOutOfBoundsException

    View Slide

  32. 2017/08/24 どこでもKotlin #m3kt
    安全性
    ● Kotlin部分は領域外アクセスなどに対し比較的安全だが、C相
    互運用部分は注意が必要
    val arr = arrayOf(1, 2, 3)
    for(i in 0..3)
    println(arr[i])
    kotlin.ArrayIndexOutOfBoundsException
    memScoped {
    val arr = intArrayOf(1, 2, 3)
    .toCValues()
    .getPointer(this)
    for (i in 0..3)
    println(arr[i])
    }
    1
    2
    3
    268435456
    こっちの方
    がまずい

    View Slide

  33. 2017/08/24 どこでもKotlin #m3kt
    実際に動かしてみる
    OpenCVで顔抽出をやってみる
    https://github.com/oboenikui/kotlin-native-sample

    View Slide

  34. 2017/08/24 どこでもKotlin #m3kt
    実際に動かしてみる
    OpenCVで顔抽出をやってみる
    ● CのレガシーAPIしか使えなくてつらい
    ● Cよりもコード量多くなりそうでつらい
    https://github.com/oboenikui/kotlin-native-sample

    View Slide

  35. 2017/08/24 どこでもKotlin #m3kt
    ● ゲーム系?
    → Unityなどのサポート次第
    ● 組み込み系?
    → なさそう(ランタイムのサイズがネックに?)
    ● WebAssembly?
    → まだ入り込む余地がありそう
    ● iOS Application?
    → 素直にSwift学ぼう
    Kotlin/Nativeが活躍できる未来は来るか?

    View Slide

  36. 2017/08/24 どこでもKotlin #m3kt
    まとめ
    ● Kotlin/Nativeの基本的な機能は整った
    ● 正直今のままではキツい部分が多い
    ○ C相互運用部分とKotlin標準部分が混ざると読みにくい
    ○ GCCなどのセキュリティチェック機能が削がれてしまっているの
    で危険なコードに気づきにくい
    ● 各ライブラリのKotlin/Native向けラッパーが出てきた
    ら辛さは変わるかも
    (でもそれJVMでよくね?)
    ● WebAssembly対応が発表されたらもう少し注目される?

    View Slide