Archive for the ‘JNI’ Category

  1. Hello, Win32 API(JNI) World!

    Posted on 5月 3rd, 2012 by cx20

    Win32 API(JNI)

    Win32 API は、Windows の機能にアクセスする為の API(Application Programming Interface)である。
    以下は JNI(Java Native Interface)による呼出し例である。
    Java からは 直接、Win32 API を呼び出すことは出来ないが、JNI 用の DLL を作成することで呼び出すことが可能となっている。

    ソースコード(Java)

    import java.io.*;
     
    public class Hello {
        static {
            System.loadLibrary("Hello");
        }
     
        public native int MessageBox( int hwnd, String text, String title, int type );
     
        public static void main(String args[]) {
            Hello hello = new Hello();
            hello.MessageBox( 0, "Hello, Win32 API(JNI) World!", "Hello, World!", 0 );
        }
    }

    C ヘッダファイル作成

    C:¥> javah -jni Hello

    ソースコード(C ヘッダファイル)

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class Hello */
     
    #ifndef _Included_Hello
    #define _Included_Hello
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     Hello
     * Method:    MessageBox
     * Signature: (ILjava/lang/String;Ljava/lang/String;I)I
     */
    JNIEXPORT jint JNICALL Java_Hello_MessageBox
      (JNIEnv *, jobject, jint, jstring, jstring, jint);
     
    #ifdef __cplusplus
    }
    #endif
    #endif

    ソースコード(C 実装ファイル)

    #include "Hello.h"
    #include <windows.h>
     
    /*
     * Class:     Hello
     * Method:    MessageBox
     * Signature: (ILjava/lang/String;Ljava/lang/String;I)I
     */
    JNIEXPORT jint JNICALL Java_Hello_MessageBox
      (JNIEnv* env, jobject me, jint hwnd, jstring text, jstring caption, jint type)
    {
    #ifdef UNICODE
        const jchar* _text = env->GetStringChars(text, 0); 
        const jchar* _caption = env->GetStringChars(caption, 0); 
        const int result = MessageBoxW(NULL, (LPCWSTR)_text, (LPCWSTR)_caption, type); 
        env->ReleaseStringChars(text, _text); 
        env->ReleaseStringChars(caption, _caption); 
    #else
        /* このコードはマルチバイト文字(MBCS)を考慮していない為、全角文字列を渡した場合に文字化けする。正しくは SJIS に変換する処理が必要。*/
        const char* _text = env->GetStringUTFChars(text, 0); 
        const char* _caption = env->GetStringUTFChars(caption, 0); 
        const int result = MessageBoxA(NULL, (LPCSTR)_text, (LPCSTR)_caption, type); 
        env->ReleaseStringUTFChars(text, _text); 
        env->ReleaseStringUTFChars(caption, _caption); 
    #endif
        return result; 
    }

    Win32 データ型と JNI データ型の対応は主に以下のようになっている。

    Win32 データ型 C/C++ データ型 JNI データ型 Java データ型
    BOOL int jboolean boolean
    BYTE char jbyte byte
    WCHAR wchar_t jchar char
    SHORT short jshort short
    INT int jint int
    LONGLONG __int64 jlong long
    FLOAT float jfloat float
    DOUBLE double jdouble double
    VOID void void void
    LPCSTR const char * jstring string
    LPCWSTR const wchar_t * jstring string

    なお、jstring については、使用時に、正しい C/C++ データ型(ANSI, MBCS / UNICODE)に適宜、変換する必要がある。

    DLL作成(Visual C++)

    C:¥> SET INCLUDE=%JAVA_HOME%include;%JAVA_HOME%includewin32;%INCLUDE%
    C:¥> cl Hello.cpp /LD /link user32.lib

    コンパイル&実行方法

    C:¥> javac Hello.java
    C:¥> java Hello

    実行結果

    ---------------------------
    Hello, World!
    ---------------------------
    Hello, Win32 API(JNI) World!
    ---------------------------
    OK   
    ---------------------------
  2. Hello, JNI World!

    Posted on 4月 10th, 2012 by cx20

    JNI

    JNA(Java Native Interface)は、Java と他の言語のインターフェイス仕様である。
    Java から C言語のライブラリの呼び出し、また、C言語から Java のライブラリの呼び出し等が可能である。
    ここでは、C言語から Java のライブラリの呼び出しのサンプルを記載する。

    ソースコード(呼び出す側(C++))

    #include <jni.h>
     
    int main( int argc, char* argv[] )
    {
        JNIEnv* env;
        JavaVM* jvm;
     
        // Java VM オプション設定
        JavaVMOption options[1];
        options[0].optionString = "-Xmx128m";
     
        JavaVMInitArgs vm_args;
        vm_args.version = JNI_VERSION_1_6;
        vm_args.options = options;
        vm_args.nOptions = 1;
     
        // Java VM 作成
        JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);
        // Class 検索
        jclass clazz = env->FindClass("Hello");
        // Method ID 取得
        jmethodID mid = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");
        // Class メソッド呼び出し
        env->CallStaticVoidMethod(clazz, mid, NULL);
        // Java VM 破棄
        jvm->DestroyJavaVM();
     
        return 0;
    }

    ソースコード(呼び出される側(Java))

    public class Hello {
        public static void main( String[] args ) {
            System.out.println( "Hello, JNI World!" );
        }
    }

    コンパイル&実行方法

    $ javac Hello.java
    $ c++ -o jnihello jnihello.cpp ¥
    -I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/ ¥
    -framework JavaVM ¥
    -m64
    $ ./jnihello

    実行結果

    Hello, JNI World!