Archive for 5月 3rd, 2012

  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   
    ---------------------------