読者です 読者をやめる 読者になる 読者になる

J/Invoke - 1.0 Released

Java C JNI

J/Invokeは,簡単にWin32 dllやLinux shared libraryを呼び出せるライブラリです.

J/Invoke is the easiest way to call functions in a Win32 DLL (or a Linux shared library) from Java.
With J/Invoke, Java programmers can call the Win32 API, or any exported function from a native DLL, with pure Java code. 

一番簡単なサンプルは以下の通り.

import com.jinvoke.JInvoke;
import com.jinvoke.NativeImport;

public class Example {
    @NativeImport(library="User32", function="MessageBox")
    public static native int showMessage(int hwnd, String text, String caption, int type);
    
    public static void main(String[] args) {
        JInvoke.initialize();
        showMessage(0, "This MessageBox is a native Win32 MessageBox", "Caption", 0);
    }
}

annotation指定によってdefaultでJ/InvokeがDLL呼び出しの際にJavaの文字列をUnicodeにconvertするのを変更出来ます.
以下の例は,charset element, convention elementの使用例

import com.jinvoke.*;

public class CRuntimeLibrary {
    @NativeImport(library="msvcrt", charset=Charset.ANSI, convention=CallingConvention.CDECL)
    public static native int strlen(String str);
    
    public static void main(String[] args) {

        JInvoke.initialize();        
        System.out.println(strlen("abcdef"));        
    }
}

目にとまったのは@NativeStruct annotationと@Embedded annotation.

typedef struct _SYSTEMTIME {
    WORD wYear;
    WORD wMonth;
    WORD wDayOfWeek;
    WORD wDay;
    WORD wHour;
    WORD wMinute;
    WORD wSecond;
    WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME;

上記のようなCの構造体をJavaで以下のように表せます.

import com.jinvoke.NativeStruct;
@NativeStruct
public class SYSTEMTIME{
    public short wYear;
    public short wMonth;
    public short wDayOfWeek;
    public short wDay;
    public short wHour;
    public short wMinute;
    public short wSecond;
    public short wMilliseconds;
}

その使用例

import com.jinvoke.JInvoke;
import com.jinvoke.NativeImport;

public class GetSystemTime {
    
    @NativeImport(library="kernel32")
    static native void GetSystemTime(SYSTEMTIME pst);

    public static void main(String[] args) {

        JInvoke.initialize();
        SYSTEMTIME systemtime = new SYSTEMTIME();
        GetSystemTime(systemtime);

        System.out.println(
              "\tyear        : " + systemtime.wYear + 
            "\n\tmonth       : " + systemtime.wMonth +

            "\n\tDayOfWeek   : " + systemtime.wDayOfWeek +
            "\n\tDay         : " + systemtime.wDay +
            "\n\tHour        : " + systemtime.wHour+

            "\n\tMinute      : " + systemtime.wMinute+
            "\n\tSecond      : " + systemtime.wSecond+
            "\n\tMillisecond : " + systemtime.wMilliseconds);

    }
}


@Embeddedの方は

typedef struct tagLOGFONT {
    LONG lfHeight;
    LONG lfWidth;
    //... some fields deleted for clarity
    TCHAR lfFaceName[32]; // embedded string of length 32 chars
} LOGFONT, *PLOGFONT; 

@Embedded(length=32)の部分

import com.jinvoke.Embedded;
import com.jinvoke.NativeStruct;

@NativeStruct
public class LogFont {
    public int lfHeight;
    public int lfWidth;
    //... some fields deleted for clarity
    @Embedded(length=32)
    public StringBuffer lfFaceName = new StringBuffer(32); // embedded string of length 32 chars
}


サポートOSは以下の通り.


落ち着いたらガシガシ使ってみます.
でもJNI使ってる人って全然聞かない...