Kotlin Academy · レッスン

cinteropと.defファイルによるC相互運用

cinteropツールと定義ファイルを使用して、Kotlin/NativeからCライブラリを呼び出します。

レッスン 3/413 ステップ

「cinteropと.defファイルによるC相互運用」はCoddyKit上の無料Kotlin Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはKotlin Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Kotlin Academyコースには全4レッスンが含まれています。

C相互運用が必要な理由

Kotlin/Native では、JNI ラッパーやブリッジングレイヤーを介さずに C ライブラリを直接呼び出せます。これにより、Kotlin コードから、プラットフォームのシステムライブラリ、ハードウェアドライバー、その他の C 互換ライブラリを、ネイティブバイナリにコンパイルして利用できます。

.defファイル

.def ファイルには、インポートする C ライブラリの情報を記述します。ヘッダー、ライブラリ名、オプションのコンパイラ/リンカーフラグを指定します。src/nativeInterop/cinterop/ に配置してください:

# src/nativeInterop/cinterop/libcurl.def
headers = curl/curl.h
headerFilter = curl/**
linkerOpts.linux = -lcurl
linkerOpts.macos = -lcurl

Gradleに相互運用を登録する

ターゲットの compilations ブロックで .def ファイルを参照します:

kotlin {
    linuxX64 {
        compilations["main"].cinterops {
            val libcurl by creating {
                defFile(project.file("src/nativeInterop/cinterop/libcurl.def"))
            }
        }
    }
}

cinteropの実行

Cヘッダーから.klibを生成するには、./gradlew cinteropLibcurlLinuxX64を実行します。生成されたKotlinバインディングはbuild/cinterop/に作成され、コンパイルのクラスパスに自動的に追加されます。

KotlinでのC関数の使用

生成後、.defファイルで宣言したパッケージをインポートし、C関数をKotlin関数として呼び出します。ポインター型はCPointer<T>として表されます。

import libcurl.*
import kotlinx.cinterop.*

fun fetchUrl(url: String): String = memScoped {
    val handle = curl_easy_init() ?: error("curl init failed")
    curl_easy_setopt(handle, CURLOPT_URL, url.cstr.ptr)
    curl_easy_perform(handle)
    curl_easy_cleanup(handle)
    "done"
}

memScoped:スタックに割り当てるメモリ

memScoped { }はメモリスコープを作成します。このスコープ内では、ネイティブメモリの割り当て(alloc()やallocArray())がブロックの終了時に自動的に解放されます。メモリリークを防ぐため、一時的なCメモリには必ず使用してください。

memScoped {
    val value = alloc<IntVar>()
    value.value = 42
    println(value.value)  // 42
    // freed automatically at end of memScoped
}

Cに渡すKotlinオブジェクトのピン留め

KotlinオブジェクトのアドレスをC関数(コールバックなど)に渡すには、GCによってオブジェクトが移動されないようにStableRefまたはPinnedでピン留めします。

val stableRef = StableRef.create(myKotlinObject)
try {
    c_function_expecting_user_data(stableRef.asCPointer())
} finally {
    stableRef.dispose()
}

C文字列とKotlin文字列

KotlinのStringとCのconst char*の間では、次の方法で変換します。

  • "hello".cstr → CValues。memScoped内で有効です
  • cPointer.toKString() → CPointer<ByteVar>からKotlin Stringへの変換
memScoped {
    val cStr = "Hello, C!".cstr.ptr   // CPointer<ByteVar>
    val back = cStr.toKString()         // "Hello, C!"
}

構造体へのアクセス

Cの構造体は、プロパティを持つKotlinクラスになります。ドット演算子を使って構造体のフィールドにアクセスします。構造体はmemScoped { }内でalloc<StructName>()を使って割り当てます。

memScoped {
    val addr = alloc<sockaddr_in>()
    addr.sin_family = AF_INET.convert()
    addr.sin_port = htons(8080u).convert()
}

インラインCコードの埋め込み

短いCコードを記述する場合は、.defファイル内のcCodeブロックを使用します。ここに記述したインラインCコードは、バインディングと一緒にコンパイルされます。

# In .def file
headers = stdio.h
---
// Inline C code after ---
static inline int add(int a, int b) { return a + b; }

C相互運用の問題のデバッグ

よくある問題には、ヘッダーが見つからない(headerFilterを確認します)、リンカーオプションが不足している(linkerOptsを追加します)、型が一致しない(生成された.klibのAPIを確認します)などがあります。defファイルまたはGradleタスクの設定で-verboseを指定すると、cinteropの詳細なログを有効にできます。

クイックチェック

Kotlin/NativeのC相互運用で、memScoped { }は何のために使用しますか。

まとめ:cinteropと.defファイルによるC相互運用

重要なポイント:

  • .defファイルでヘッダー、リンカーオプション、オプションのインラインCコードを指定します
  • cinterops { val name by creating { defFile(...) } }でGradleに登録します
  • cinterop<Name><Target> Gradleタスクを実行してバインディングを生成します
  • 一時的なネイティブメモリの割り当てにはmemScoped { }を使用します
  • 長期間使用するオブジェクトはStableRefでピン留めし、文字列は.cstr/.toKString()で変換します
無料で開始

AI チューターと学ぶ Kotlin — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
51
レッスン
203

よくある質問

「cinteropと.defファイルによるC相互運用」レッスンは無料ですか?

はい。「cinteropと.defファイルによるC相互運用」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Kotlin Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Kotlin Academyコースには全4レッスンが含まれています。

「cinteropと.defファイルによるC相互運用」で何を学びますか?

cinteropツールと定義ファイルを使用して、Kotlin/NativeからCライブラリを呼び出します。 ブラウザで直接実行するハンズオンコードでKotlin Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Kotlin Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのKotlin Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「cinteropと.defファイルによるC相互運用」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このKotlin Academyレッスンでコードを書いて実行できますか?

はい。すべてのKotlin Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Kotlin/Nativeの概要:ターゲット、ツールチェーン、コンパイル
  2. Kotlin/Nativeのメモリ管理:新しいMM
  3. cinteropと.defファイルによるC相互運用
  4. Kotlin/WASM:ブラウザー向けWebAssemblyへのコンパイル
← Kotlin Academyに戻る