Java Native Interface(4)

マルチスレッドに対応するために、WmiCallをstaticで処理しないよう修正しました。
JavaのWmiCallのメソッドをstaticで無くして、
WmiCall.java

package wmi;

public class WmiCall {

    private long handle = 0;

    static {
        System.loadLibrary("jniwmi");
        classinit();
    }

    public WmiCall() {
    }

    private static native void classinit();

    public native boolean init();
    public native void term();
    public native WmiResult access(String query, boolean withValue);
    public native WmiResult link(String query, boolean withValue);
}

コンパイルした後で、javahで再度ヘッダファイルを作成し、
wmi_WmiCall.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class wmi_WmiCall */

#ifndef _Included_wmi_WmiCall
#define _Included_wmi_WmiCall
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     wmi_WmiCall
 * Method:    classinit
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_wmi_WmiCall_classinit
  (JNIEnv *, jclass);

/*
 * Class:     wmi_WmiCall
 * Method:    init
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL Java_wmi_WmiCall_init
  (JNIEnv *, jobject);

/*
 * Class:     wmi_WmiCall
 * Method:    term
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_wmi_WmiCall_term
  (JNIEnv *, jobject);

/*
 * Class:     wmi_WmiCall
 * Method:    access
 * Signature: (Ljava/lang/String;Z)Lwmi/WmiResult;
 */
JNIEXPORT jobject JNICALL Java_wmi_WmiCall_access
  (JNIEnv *, jobject, jstring, jboolean);

/*
 * Class:     wmi_WmiCall
 * Method:    link
 * Signature: (Ljava/lang/String;Z)Lwmi/WmiResult;
 */
JNIEXPORT jobject JNICALL Java_wmi_WmiCall_link
  (JNIEnv *, jobject, jstring, jboolean);

#ifdef __cplusplus
}
#endif
#endif

WmiCallクラスを、そのヘッダに対応した関数に書き直しました。
jniwmi.cpp

/*
 *  WmiCallからの結果をJavaのクラスに展開する処理
 */
jobject load_class(JNIEnv *env, WmiResult results) {
    /*
     *  WmiResultオブジェクトの生成
     */
    jobject wmiObj = env->NewObject(wr_class, wr_ctor);

    /*
     *  プロパティ値の設定
     */
    size_t prop_count = results.items();
    jobjectArray properties = env->NewObjectArray((jsize)prop_count, str_class, NULL);
    for (size_t i = 0; i < prop_count; i++) {
        _bstr_t prop = _bstr_t((_TCHAR *)results.getProperty(i).c_str());
        jobject prop_str = env->NewString((const jchar *)((wchar_t *)prop), (jsize)prop.length());
        env->SetObjectArrayElement(properties, (jsize)i, prop_str);
    }
    env->SetObjectField(wmiObj, wr_propertiesID, properties);

    /*
     *  戻り値の設定
     */
    size_t row = results.size();
    jobjectArray result = env->NewObjectArray((jsize)row, vector_class, NULL);
    for (size_t i = 0; i < row; i++) {
        jobject vector = env->NewObject(vector_class, vector_init);
        for (size_t j = 0; j < prop_count; j++) {
            String prop = results.getProperty(j);
            _bstr_t entry;
            VARIANT *value = results.getValue(prop, i);
            if (WmiResult::getType(value) == VT_BSTR) {
                entry = _bstr_t(WmiResult::isByRef(value) ? *value->pbstrVal : value->bstrVal);
            }
            else {
                entry = _bstr_t((_TCHAR *)WmiResult::getString(value).c_str());
            }
            jobject entry_str = env->NewString((const jchar *)((wchar_t *)entry), (jsize)entry.length());
            jboolean res = env->CallBooleanMethod(vector, vector_add, entry_str);
        }
        env->SetObjectArrayElement(result, (jsize)i, vector);
    }
    env->SetObjectField(wmiObj, wr_resultID, result);
    return wmiObj;
}

/*
 *  JNIの初期化処理
 */
JNIEXPORT void JNICALL Java_wmi_WmiCall_classinit(JNIEnv *env, jclass cls) {
    wc_class = (jclass)env->NewGlobalRef(cls);
    wc_ctor = env->GetMethodID(wc_class, "<init>", "()V");
    wc_handle = env->GetFieldID(wc_class, "handle", "J");

    /*
     *  WmiResultクラスの情報を設定
     */
    wr_class = env->FindClass("wmi/WmiResult");
    wr_class = (jclass)env->NewGlobalRef(wr_class);
    wr_propertiesID = env->GetFieldID(wr_class, "properties", "[Ljava/lang/String;");
    wr_resultID = env->GetFieldID(wr_class, "result", "[Ljava/util/Vector;");
    wr_ctor = env->GetMethodID(wr_class, "<init>", "()V");

    /*
     *  Stringクラスの情報を設定
     */
    jclass clazz = env->FindClass("java/lang/String");
    str_class = (jclass)env->NewGlobalRef(clazz);
    env->DeleteLocalRef(clazz);

    /*
     *  Vectorクラスの情報を設定
     */
    clazz = env->FindClass("java/util/Vector");
    vector_class = (jclass)env->NewGlobalRef(clazz);
    vector_init = env->GetMethodID(vector_class, "<init>", "()V");
    vector_add = env->GetMethodID(vector_class, "add", "(Ljava/lang/Object;)Z");
    env->DeleteLocalRef(clazz);
}

/*
 *  public native boolean init()
 */
JNIEXPORT jboolean JNICALL Java_wmi_WmiCall_init(JNIEnv *env, jobject obj) {
    WmiCall *wmi = new WmiCall();
    wmi->init();
    if (wmi->initialized()) {
        env->SetLongField(obj, wc_handle, (jlong)wmi);
        return true;
    }
    return false;
}

/*
 *  public native void term()
 */
JNIEXPORT void JNICALL Java_wmi_WmiCall_term(JNIEnv *env, jobject obj) {
    WmiCall *wmi = (WmiCall *)env->GetLongField((jobject)obj, wc_handle);
    if ((wmi != NULL) && (wmi->initialized())) {
        wmi->term();
        env->SetLongField(obj, wc_handle, (jlong)0);
    }
}

/*
 *  public native WmiResult access(String query, boolean withValue)
 */
JNIEXPORT jobject JNICALL Java_wmi_WmiCall_access(JNIEnv *env, jobject obj, jstring query, jboolean with_value) {
    WmiResult results;
    WmiCall *wmi = (WmiCall *)env->GetLongField(obj, wc_handle);
    if ((wmi != NULL) && (wmi->initialized())) {
        const jchar *query_buf  = env->GetStringChars(query, NULL);
        _bstr_t query_stmt = _bstr_t((wchar_t*)query_buf);
        env->ReleaseStringChars(query, query_buf);

        String select_stmt = String((_TCHAR *)query_stmt);
        results = wmi->access(select_stmt, (with_value != 0) ? true : false);
    }
    return load_class(env, results);
}

/*
 *  public native WmiResult link(String query, boolean withValue)
 */
JNIEXPORT jobject JNICALL Java_wmi_WmiCall_link(JNIEnv *env, jobject obj, jstring query, jboolean with_value) {
    WmiResult results;
    WmiCall *wmi = (WmiCall *)env->GetLongField(obj, wc_handle);
    if ((wmi != NULL) && (wmi->initialized())) {
        const jchar *query_buf  = env->GetStringChars(query, NULL);
        _bstr_t query_stmt = _bstr_t((wchar_t*)query_buf);
        env->ReleaseStringChars(query, query_buf);

        String select_stmt = String((_TCHAR *)query_stmt);
        results = wmi->link(select_stmt, (with_value != 0) ? true : false);
    }
    return load_class(env, results);
}

この時一緒に、C++のWmiCallクラスの初期化処理が正常終了したか、などのチェックを行うことも修正しました。