jextract
jextractはOpenJDKが開発しているツールで、CやC++のヘッダファイル(.h)を読み込んで、FFM APIを使うためのJavaバインディングクラスを自動生成するものです。
何が嬉しいのか
FFM APIでネイティブライブラリを呼ぶには、関数のシグネチャ(引数の型・戻り値の型)をJavaコードで手動で記述する必要があります。例えばCの関数:
code:c
// Python C API の例
PyObject* PyLong_FromLong(long v);
をFFM APIで手書きすると:
code:java
// 手書きだとこうなる
FunctionDescriptor desc = FunctionDescriptor.of(
ValueLayout.ADDRESS, // 戻り値: PyObject*
ValueLayout.JAVA_LONG // 引数: long
);
MethodHandle PyLong_FromLong = linker.downcallHandle(
lookup.find("PyLong_FromLong").get(), desc
);
これをPython C APIの数百〜数千の関数に対して手書きするのは現実的ではありません。
jextractを使えば、python.hを渡すだけで上記のようなMethodHandle定数やレイアウト定義を自動生成してくれます。detroit-pythonの場合、生成されたPython_h.javaがそれで、コード中のimport static org.openjdk.engine.python.bindings.Python_h.*がその使用箇所です。
立ち位置のイメージ
code:_
python.h(CのAPIヘッダ)
↓ jextractで自動生成
Python_h.java(FFM APIのバインディング)
↓ Javaコードから使う
PythonScriptEngine.java など
JNI時代は同じことをjavahコマンド+C側の実装で行っていましたが、jextractはそれをFFM APIベースで置き換える、より現代的なアプローチです。