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クラスの初期化処理が正常終了したか、などのチェックを行うことも修正しました。