Java Native Interface(2-2)
Javawをコンパイルした後に、JNI用にヘッダファイルを生成します。
# javah wmi/WmiCall.class
で、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 *, jclass); /* * Class: wmi_WmiCall * Method: term * Signature: ()V */ JNIEXPORT void JNICALL Java_wmi_WmiCall_term (JNIEnv *, jclass); /* * Class: wmi_WmiCall * Method: access * Signature: (Ljava/lang/String;Z)Lwmi/WmiResult; */ JNIEXPORT jobject JNICALL Java_wmi_WmiCall_access (JNIEnv *, jclass, jstring, jboolean); /* * Class: wmi_WmiCall * Method: link * Signature: (Ljava/lang/String;Z)Lwmi/WmiResult; */ JNIEXPORT jobject JNICALL Java_wmi_WmiCall_link (JNIEnv *, jclass, jstring, jboolean); #ifdef __cplusplus } #endif #endif
呼び出されるDLLは、WmiCallでSystem.loadLibrary("jniwmi");と記述してあるので、jniwmi.dllという名前で作成します。
ヘッダファイルは
jniwmi.h
#ifndef _JNI_WMI_CALL #define _JNI_WMI_CALL #include <windows.h> #include "wmi.h" #include "wmi_WmiCall.h" jclass wc_class; /* WmiCall */ jmethodID wc_ctor; /* WmiCall() */ jclass wr_class; /* WmiResult */ jmethodID wr_ctor; /* WmiResult() */ jfieldID wr_propertiesID; /* WmiResult.properties */ jfieldID wr_resultID; /* WmiResult.result */ jclass str_class; /* String */ jclass vector_class; /* Vector */ jmethodID vector_init; /* Vector() */ jmethodID vector_add; /* Vector.add(Object) */ #endif // _JNI_WMI_CALL
プログラム本体は
#include "jniwmi.h" BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { return TRUE; } static WmiCall wmi; /* * WmiCallからの結果をJavaのクラスに展開する処理 */ jobject load_class(JNIEnv *env, jclass cls, 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(); if (row > 0) { 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 = _bstr_t((_TCHAR *)results.getString(prop, i).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"); /* * 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 static native boolean init() */ JNIEXPORT jboolean JNICALL Java_wmi_WmiCall_init(JNIEnv *env, jclass cls) { wmi.init(); return wmi.initialized(); } /* * public static native void term() */ JNIEXPORT void JNICALL Java_wmi_WmiCall_term(JNIEnv *env, jclass cls) { wmi.term(); } /* * public static native WmiResult access(String query, boolean withValue) */ JNIEXPORT jobject JNICALL Java_wmi_WmiCall_access(JNIEnv *env, jclass cls, jstring query, jboolean with_value) { 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); WmiResult results = wmi.access(select_stmt, (with_value != 0) ? true : false); return load_class(env, cls, results); } /* * public static native WmiResult link(String query, boolean withValue) */ JNIEXPORT jobject JNICALL Java_wmi_WmiCall_link(JNIEnv *env, jclass cls, jstring query, jboolean with_value) { 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); WmiResult results = wmi.link(select_stmt, (with_value != 0) ? true : false); return load_class(env, cls, results); }
このままだと、SAFEARRAYの処理が出来ていないのと、C++ライブラリのWmiCallをstaticに保存しているのでマルチスレッドには対応できないので、この先頑張って対応していきます。
ただ、明日から遅い夏休みなので、続きは来週以降ということで・・・。