S-JIS[2024-09-23] 変更履歴
Javaの外部関数およびメモリーAPIのSymbolLookupのメモ。
|
SymbolLookupは、シンボルのポインターを取得する為のインターフェース。
import java.lang.foreign.SymbolLookup;
SymbolLookupのインスタンスを取得する方法は、どのライブラリーを対象とするか(どのライブラリーを読み込むか)で異なる。
System.load()で読み込んだライブラリーを対象とする場合は、loaderLookupを使う。
System.load("C:/example/ffi/ffi-example-rust/target/release/ffi_example_rust.dll"); SymbolLookup symbolLookup = SymbolLookup.loaderLookup();
System.load()にはライブラリーファイルのパスを指定する。
System.loadLibrary()で読み込んだライブラリーを対象とする場合も、loaderLookupを使う。
System.loadLibrary("ffi_example_rust"); SymbolLookup symbolLookup = SymbolLookup.loaderLookup();
System.loadLibrary()にはライブラリーファイルのファイル名(拡張子無し)を指定する。
ffi_example_rustを指定した場合、実際に読まれるファイルは、Windowsならffi_example_rust.dllになるし、Linuxならffi_example_rust.soになるはず。
System.loadLibrary()を使う場合は、実行時にライブラリーファイルの場所(ディレクトリー)を指定してやる必要がある。
javaコマンドの-Djava.library.path
オプションか、環境変数(Linuxの場合はLD_LIBRARY_PATH、Windowsの場合はPATH)でライブラリーファイルのディレクトリーを指定する。
> java -Djava.library.path=C:/example/ffi/ffi-example-rust/target/release com.example.ffi.FfiExample
OSの標準ライブラリーを使いたい場合は、LinkerのdefaultLookupを使う。
import java.lang.foreign.Linker;
Linker linker = Linker.nativeLinker(); SymbolLookup stdLib = linker.defaultLookup();
OSの特定のライブラリーを使いたい場合は、libraryLookupでライブラリー名を指定する。
SymbolLookup stdLib = SymbolLookup.libraryLookup("libc.so.6", arena);
libraryLookupでライブラリーファイルのパスを指定できる。
import java.nio.file.Path;
var path = Path.of("C:/example/ffi/ffi-example-rust/target/release/ffi_example_rust.dll"); var symbolLookup = SymbolLookup.libraryLookup(path, arena);
メソッド | 説明 | 例 |
---|---|---|
Optional<MemorySegment> find(String name) |
シンボルを取得する。 見つからなかった場合はOptional.empty()が返る。 |
MemorySegment add = symbolLookup.find("add").orElseThrow(); |
MemorySegment findOrThrow(String name) |
シンボルを取得する。(Java23以降) 見つからなかった場合はNoSuchElementExceptionがスローされる。 |
MemorySegment add = symbolLookup.findOrThrow("add"); |
SymbolLookup or(SymbolLookup other) |
SymbolLookupのチェーン。 | var lookup = SymbolLookup.libraryLookup("foo", arena) |
「find("add").orElseThrow()
」の場合、シンボルが見つからなかったら「NoSuchElementException: No value present」がスローされることになる。(メッセージの中にシンボル名は出てこない)
「findOrThrow("add")
」であれば、「NoSuchElementException: Symbol not found: add」のようにシンボル名がメッセージの中に含まれているので分かりやすい。