Java Native Interface(3)
久々の更新です。
今日まで夏休みなんですが、どうしても気になっていたので作業することにしました。
と言うのは、C++コンパイル時の文字コードを"MBCS"から"UNICODE"にすると漢字が化けてしまったので、これを補正するために修正しました。
変更を加えたのは、jniwmi.cppのload_classの中で戻り値を設定する部分です。
/* * 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; 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; }
戻りデータのタイプが"VT_BSTR"の時に、WmiResultクラスのgetStringメソッドで文字変換させるのではなく、load_class関数の中で行うことにしました。
テストしたプログラムは、
package wmi.test; import wmi.WmiCall; import wmi.WmiResult; public class WmiCallTest { public WmiCallTest() { WmiCall wmi = new WmiCall(); wmi.init(); WmiResult logical_disk = wmi.access("SELECT * FROM Win32_LogicalDisk WHERE DeviceID = \"C:\"", true); System.out.println(logical_disk.print()); wmi.term(); } public static void main(String[] argv) { new WmiCallTest(); } }
これで、テストプログラムを実行した時に"Description"には正しくデータが表示できました。
C++のプログラムで処理している限りは何も問題なかったんだけど、Javaでアクセスすると文字が化けるんだよなぁ???