Skip to content

定義ファイル

Kotlin/Nativeを使用すると、CおよびObjective-Cライブラリを利用して、その機能をKotlinで使用できます。cinteropと呼ばれる特別なツールは、CまたはObjective-Cライブラリを受け取り、対応するKotlinバインディングを生成するため、ライブラリのメソッドを通常通りKotlinコードで使用できます。

これらのバインディングを生成するには、各ライブラリに定義ファイルが必要です。これは通常、ライブラリと同じ名前を持ちます。これは、ライブラリがどのように利用されるべきかを正確に記述するプロパティファイルです。利用可能なプロパティの全リストについては、プロパティを参照してください。

プロジェクトで作業する際の一般的なワークフローを以下に示します。

  1. バインディングに何を含めるかを記述する.defファイルを作成します。
  2. 生成されたバインディングをKotlinコードで使用します。
  3. Kotlin/Nativeコンパイラを実行して最終的な実行可能ファイルを生成します。

定義ファイルの作成と設定

Cライブラリの定義ファイルを作成し、バインディングを生成しましょう。

  1. IDEでsrcフォルダーを選択し、ファイル | 新規 | ディレクトリで新しいディレクトリを作成します。

  2. 新しいディレクトリにnativeInterop/cinteropという名前を付けます。

    これは.defファイルの場所に関するデフォルトの慣例ですが、異なる場所を使用する場合はbuild.gradle.ktsファイルで上書きできます。

  3. 新しいサブフォルダーを選択し、ファイル | 新規 | ファイルpng.defファイルを作成します。

  4. 必要なプロパティを追加します。

    none
    headers = png.h
    headerFilter = png.h
    package = png
    
    compilerOpts.linux = -I/usr/include -I/usr/include/x86_64-linux-gnu
    linkerOpts.osx = -L/opt/local/lib -L/usr/local/opt/png/lib -lpng
    linkerOpts.linux = -L/usr/lib/x86_64-linux-gnu -lpng
    • headersは、Kotlinスタブを生成するヘッダーファイルのリストです。このエントリには複数のファイルを追加でき、それぞれをスペースで区切ります。この場合、png.hのみです。参照されるファイルは、指定されたパス(この場合は/usr/include/png)で利用可能である必要があります。

    • headerFilterは、具体的に何が含まれるかを示します。Cでは、あるファイルが別のファイルを#includeディレクティブで参照すると、すべてのヘッダーも含まれます。時にはこれは不要な場合があり、globパターンを使用してこのパラメータを追加することで調整できます。

      headerFilterは、外部依存関係(システムstdint.hヘッダーなど)をinteropライブラリに取り込みたくない場合に使用できます。また、ライブラリサイズの最適化や、システムと提供されるKotlin/Nativeコンパイル環境間の潜在的な競合を修正するのに役立つ場合があります。

    • 特定のプラットフォームの動作を変更する必要がある場合、compilerOpts.osxcompilerOpts.linuxのような形式を使用して、プラットフォーム固有の値をオプションに提供できます。この場合、それらはmacOS(.osxサフィックス)とLinux(.linuxサフィックス)です。サフィックスなしのパラメータ(例: linkerOpts=)も可能で、すべてのプラットフォームに適用されます。

  5. バインディングを生成するには、通知でSync NowをクリックしてGradleファイルを同期します。

    Synchronize the Gradle files

バインディング生成後、IDEはそれらをネイティブライブラリのプロキシビューとして使用できます。

コマンドラインでcinteropツールを使用してバインディングの生成を設定することもできます。

プロパティ

以下は、生成されるバイナリの内容を調整するために定義ファイルで使用できるプロパティの全リストです。詳細については、以下の対応するセクションを参照してください。

PropertyDescription
headersバインディングに含めるライブラリのヘッダーのリスト。
modulesバインディングに含めるObjective-CライブラリのClangモジュールのリスト。
language言語を指定します。デフォルトではCが使用されます。必要に応じてObjective-Cに変更します。
compilerOptscinteropツールがCコンパイラに渡すコンパイラオプション。
linkerOptscinteropツールがリンカーに渡すリンカーオプション。
excludedFunctions無視すべき関数名のスペース区切りリスト。
staticLibraries実験的。スタティックライブラリを.klibに含めます。
libraryPaths実験的。cinteropツールが.klibに含めるライブラリを検索するディレクトリのスペース区切りリスト。
packageName生成されるKotlin APIのパッケージプレフィックス。
headerFilterライブラリをインポートする際に、globでヘッダーをフィルタリングし、それらのみを含めます。
excludeFilterライブラリをインポートする際に特定のヘッダーを除外し、headerFilterよりも優先されます。
strictEnumsKotlin enumとして生成すべきenumのスペース区切りリスト。
nonStrictEnums整数値として生成すべきenumのスペース区切りリスト。
noStringConversionconst char*パラメータがKotlin Stringに自動変換されるべきではない関数のスペース区切りリスト。
allowedOverloadsForCFunctionsデフォルトでは、C関数は一意の名前を持つと仮定されます。複数の関数が同じ名前を持つ場合、1つだけが選択されます。ただし、allowedOverloadsForCFunctionsでこれらの関数を指定することで、これを変更できます。
disableDesignatedInitializerChecks非指定Objective-Cイニシャライザをsuper()コンストラクタとして呼び出すことを許可しないコンパイラチェックを無効にします。
foreignExceptionModeObjective-Cコードからの例外をForeignException型のKotlin例外にラップします。
userSetupHintたとえば、ユーザーがリンカーエラーを解決するのに役立つカスタムメッセージを追加します。

プロパティのリストに加えて、定義ファイルにカスタム宣言を含めることができます。

ヘッダーのインポート

CライブラリがClangモジュールを持たず、代わりにヘッダーのセットで構成されている場合、headersプロパティを使用してインポートすべきヘッダーを指定します。

none
headers = curl/curl.h

globによるヘッダーのフィルタリング

.defファイルのフィルタープロパティを使用して、globでヘッダーをフィルタリングできます。ヘッダーからの宣言を含めるには、headerFilterプロパティを使用します。ヘッダーがいずれかのglobに一致する場合、その宣言はバインディングに含まれます。

globは、適切なインクルードパス要素に対する相対的なヘッダーパス(例: time.hcurl/curl.h)に適用されます。したがって、ライブラリが通常#include <SomeLibrary/Header.h>でインクルードされる場合、おそらく以下のフィルターでヘッダーをフィルタリングできます。

none
headerFilter = SomeLibrary/**

headerFilterが指定されていない場合、すべてのヘッダーが含まれます。ただし、headerFilterを使用し、globをできるだけ正確に指定することをお勧めします。この場合、生成されたライブラリには必要な宣言のみが含まれます。これは、Kotlinや開発環境のツールをアップグレードする際に発生する様々な問題を回避するのに役立ちます。

ヘッダーの除外

特定のヘッダーを除外するには、excludeFilterプロパティを使用します。これは、不要なヘッダーや問題のあるヘッダーを削除し、コンパイルを最適化するのに役立ちます。指定されたヘッダーからの宣言はバインディングに含まれないためです。

none
excludeFilter = SomeLibrary/time.h

同じヘッダーがheaderFilterで含まれ、かつexcludeFilterで除外された場合、その指定されたヘッダーはバインディングに含まれません。

モジュールのインポート

Objective-CライブラリがClangモジュールを持っている場合、modulesプロパティを使用して、インポートするモジュールを指定します。

none
modules = UIKit

コンパイラおよびリンカーオプションの受け渡し

compilerOptsプロパティを使用して、内部でヘッダーを分析するために使用されるCコンパイラにオプションを渡します。最終的な実行可能ファイルをリンクするために使用されるリンカーにオプションを渡すには、linkerOptsを使用します。例:

none
compilerOpts = -DFOO=bar
linkerOpts = -lpng

特定のターゲットにのみ適用されるターゲット固有のオプションも指定できます。

none
compilerOpts = -DBAR=bar
compilerOpts.linux_x64 = -DFOO=foo1
compilerOpts.macos_x64 = -DFOO=foo2

この設定では、ヘッダーはLinuxで-DBAR=bar -DFOO=foo1を使用し、macOSで-DBAR=bar -DFOO=foo2を使用して分析されます。定義ファイルオプションは、共通部分とプラットフォーム固有部分の両方を持つことができることに注意してください。

特定の関数を無視する

excludedFunctionsプロパティを使用して、無視すべき関数名のリストを指定します。これは、ヘッダーで宣言された関数が呼び出し可能であることが保証されておらず、これを自動的に判断するのが困難または不可能な場合に役立ちます。このプロパティを、interop自体のバグを回避するためにも使用できます。

スタティックライブラリを含める

この機能は実験的です。いつでも廃止または変更される可能性があります。評価目的のみに使用してください。

ユーザーの環境で利用可能であると仮定するよりも、製品にスタティックライブラリを同梱する方が便利な場合があります。スタティックライブラリを.klibに含めるには、staticLibrarieslibraryPathsプロパティを使用します。

none
headers = foo.h
staticLibraries = libfoo.a
libraryPaths = /opt/local/lib /usr/local/opt/curl/lib

上記のスニペットが与えられると、cinteropツールは/opt/local/lib/usr/local/opt/curl/liblibfoo.aを検索し、見つかった場合、ライブラリバイナリをklibに含めます。

プログラムでこのようにklibを使用すると、ライブラリは自動的にリンクされます。

enumの生成を設定する

strictEnumsプロパティを使用してenumをKotlin enumとして生成するか、nonStrictEnumsを使用して整数値として生成します。いずれのリストにもenumが含まれていない場合、ヒューリスティックに基づいて生成されます。

文字列変換の設定

noStringConversionプロパティを使用して、const char*関数パラメータのKotlin Stringへの自動変換を無効にします。

非指定イニシャライザの呼び出しを許可する

デフォルトでは、Kotlin/Nativeコンパイラは非指定Objective-Cイニシャライザをsuper()コンストラクタとして呼び出すことを許可しません。この動作は、指定されたObjective-Cイニシャライザがライブラリ内で適切にマークされていない場合に不便になる可能性があります。これらのコンパイラチェックを無効にするには、disableDesignatedInitializerChecksプロパティを使用します。

Objective-C例外の処理

デフォルトでは、Objective-C例外がObjective-CからKotlinへのinterop境界に到達し、Kotlinコードに渡された場合、プログラムはクラッシュします。

Objective-C例外をKotlinに伝播するには、foreignExceptionMode = objc-wrapプロパティでラッピングを有効にします。この場合、Objective-C例外はForeignException型を持つKotlin例外に変換されます。

リンカーエラーの解決を支援する

KotlinライブラリがCまたはObjective-Cライブラリに依存している場合、たとえばCocoaPods連携を使用している場合、リンカーエラーが発生する可能性があります。依存ライブラリがマシンにローカルでインストールされていないか、プロジェクトのビルドスクリプトで明示的に設定されていない場合、「Framework not found」エラーが発生します。

ライブラリの作者である場合、カスタムメッセージでユーザーがリンカーエラーを解決するのを支援できます。これを行うには、.defファイルにuserSetupHint=messageプロパティを追加するか、-Xuser-setup-hintコンパイラオプションをcinteropに渡します。

カスタム宣言の追加

バインディングを生成する前に、カスタムC宣言をライブラリに追加する必要がある場合があります(たとえば、マクロの場合など)。これらの宣言を含む追加のヘッダーファイルを作成する代わりに、区切り行(区切りシーケンス---のみを含む行)の後に、.defファイルの末尾に直接含めることができます。

none
headers = errno.h
---

static inline int getErrno() {
    return errno;
}

.defファイルのこの部分はヘッダーファイルの一部として扱われるため、本体を持つ関数はstaticとして宣言する必要があることに注意してください。宣言はheadersリストからのファイルが含まれた後にパースされます。

コマンドラインを使用したバインディングの生成

定義ファイルに加えて、cinterop呼び出しで対応するプロパティをオプションとして渡すことで、バインディングに何を含めるかを指定できます。

png.klibコンパイル済みライブラリを生成するコマンドの例を以下に示します。

bash
cinterop -def png.def -compiler-option -I/usr/local/include -o png

生成されたバインディングは一般的にプラットフォーム固有であるため、複数のターゲット向けに開発している場合、バインディングを再生成する必要があることに注意してください。

  • sysroot検索パスに含まれていないホストライブラリの場合、ヘッダーが必要になる場合があります。
  • 設定スクリプトを持つ一般的なUNIXライブラリの場合、compilerOptsには、--cflagsオプションを持つ設定スクリプトの出力(正確なパスなしで)が含まれる可能性が高いです。
  • --libsを持つ設定スクリプトの出力は、linkerOptsプロパティに渡すことができます。

次のステップ