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 目次 1. Kotlin/Nativeとは? a. LLVMとは? b. できること・できないこと

    2. Kotlin/Nativeを使い始める 3. おなじところ、ちがうところ 4. 使ってみた
  2. 2017/08/24 どこでもKotlin #m3kt 自己紹介 • 星川 貴樹 (@oboenikui) • 17卒の入社5ヶ月目

    • 現在の仕事は主にAndroidアプリ • 野球(見る方)、CTFが趣味
  3. 2017/08/24 どこでもKotlin #m3kt できること・できないこと • ˉできるˉ ◦ kotlin.*パッケージに含まれるクラス・メソッドを使う ◦ Cのヘッダーファイルが使えるライブラリを使う

    ◦ デバッグ • ˈできないˈ ◦ Fileクラスのようにkotlin.*パッケージに含まれないJavaの クラスを使う ◦ Javaのライブラリを使う ◦ Cのヘッダーファイルを含まないライブラリを使う※
  4. 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/
  5. 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:+" } }
  6. 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; }
  7. 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の外部ライブラリ呼び出しの記法と同じ
  8. 2017/08/24 どこでもKotlin #m3kt Cのための相互運用型・メソッド • signed, unsignedな整数・浮動小数点型の数値は、同じ幅の数値型に マップ (32bit幅の整数の場合unsignedでもInt) •

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

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

    ポインタ・配列はCPointer<T>?にマップ • enumはenumか整数値にマップ • 構造体はCStructVarを継承したクラスにマップ • typedefはtypealiasにマップ • C相互運用のための拡張関数が定義されている など (例) val path = getenv("PATH")?.toKString() ?: ""
  11. 2017/08/24 どこでもKotlin #m3kt メモリ管理 Cとの相互運用部分 val buffer = nativeHeap.allocArray<ByteVar>(64 *

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

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

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

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

    val bufferLength = 64 * 1024 val buffer = allocArray<ByteVar>(bufferLength) fgets(buffer, bufferLength, file)? .toKString() ?: "" }
  16. 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]) }
  17. 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
  18. 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 こっちの方 がまずい
  19. 2017/08/24 どこでもKotlin #m3kt • ゲーム系? → Unityなどのサポート次第 • 組み込み系? →

    なさそう(ランタイムのサイズがネックに?) • WebAssembly? → まだ入り込む余地がありそう • iOS Application? → 素直にSwift学ぼう Kotlin/Nativeが活躍できる未来は来るか?
  20. 2017/08/24 どこでもKotlin #m3kt まとめ • Kotlin/Nativeの基本的な機能は整った • 正直今のままではキツい部分が多い ◦ C相互運用部分とKotlin標準部分が混ざると読みにくい

    ◦ GCCなどのセキュリティチェック機能が削がれてしまっているの で危険なコードに気づきにくい • 各ライブラリのKotlin/Native向けラッパーが出てきた ら辛さは変わるかも (でもそれJVMでよくね?) • WebAssembly対応が発表されたらもう少し注目される?