LoginSignup
34
29

More than 5 years have passed since last update.

JavaからC言語で書かれた処理を呼ぶ。(JNA)

Posted at

はじめに

JavaからC言語で書かれた処理を呼ぶ必要が出てきたため、調べたことをメモしておきます。
昔の知識でJNI(Java Native Interface)を使うものだと思っていたけれど、
最近ではJNA(Java Native Access)という便利なクラスライブラリがあって、
驚くほど簡単に呼び出せます。

JNAライブラリの入手

以下のWebサイトからダウンロードできます。
https://github.com/twall/jna#download

  • jna.jar

サンプルコード1 (静的にマッピング)

C言語の標準ライブラリであるprintfを呼び出すサンプルです。(上記サイトを参考)
まず、呼び出したい関数をinterfaceで定義しておきます。
このインタフェースをNative#loadLibrary()メソッドにかけるとあら不思議、
ライブラリ関数を呼ぶインスタンスが生成されます。

HelloWorld.java
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;

public class HelloWorld {
    public interface CLibrary extends Library {
        CLibrary INSTANCE = (CLibrary) Native.loadLibrary(
            Platform.isWindows() ? "msvcrt" : "c",
            CLibrary.class);

        void printf(String format, Object... args);
    }

    public static void main(String[] args) {
        CLibrary.INSTANCE.printf("Hello, World\n");
    }
}

サンプルコード2(動的にマッピング)

呼び出したいライブラリや関数がパラメータなどで渡され、動的に決まる場合はどうしたらいいの?
今回、実装したい処理はまさにこのケースだったので、あらかじめinterfaceを定義できないし、
javax.tools.JavaCompilerを使ってinterfaceを動的に生成して・・・という検証用コードを
思わず書いてしまったのですが、実はそんなに頑張らなくても簡単にできました。

HelloWorld.java
import com.sun.jna.Function;
import com.sun.jna.Platform;

public class HelloWorld {
    public static void main(String[] args) {
        String libraryName  = Platform.isWindows() ? "msvcrt" : "c";
        String functionName = "printf";

        // Function
        Function function = Function.getFunction(
            libraryName,
            functionName,
            Function.C_CONVENTION);

        // Invoke
        function.invoke(new Object[]{"Hello, world\n"});
    }
}
34
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
34
29