C++からjavaを実行する方法。VisualStudio2010とjava8。
参考にさせていただいたサイト。
http://www.ne.jp/asahi/hishidama/home/tech/java/jni_vm.htmlhttps://blogs.yahoo.co.jp/dk521123/33067170.html
概要
諸事情あってC++からJavaを呼び出す際のコードです。先述のサイト様の実装例といったところです。
環境
- VisualStudio 2010 sp1
- java 1.8 191
- WindowsServer2008 sp1
以下コード
*blog掲載に際し、一部でプロジェクト固有の文字が入っていたため、適当に削除しました。**メソッドはblog用に一つにしてありますが、jvm使い回し箇所など適宜関数化すればよいかと思います。
#include#include "myApp.h" #include #include "jni.h" #pragma comment(lib, "jvm.lib") using namespace std; static JavaVM* vm(NULL); int cppExecute ( int id ) { // jvmの用意 JNIEnv *env; JavaVMInitArgs vm_args; JavaVMOption options[2]; options[0].optionString = "-Djava.class.path=xxx.jar"; options[1].optionString = "-Xmx256m"; //値はblog用に適当 vm_args.version = JNI_VERSION_1_8; vm_args.options = options; vm_args.nOptions = 2; // JVM使いまわしチェック。初回はJVMが未Createなのでそちらのルート。 // 2回目以降はCreate済みのJVMを使用する。 if (vm == NULL ) { // JVMが存在しない。(初回) int result = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args); if (result != 0) { // プログラムエラー return -1; } } else { // JVMは一度Create済み。 jint ret = vm->GetEnv((void**)&env, JNI_VERSION_1_8); if ( ret == JNI_EDETACHED ) { //attache ret = vm->AttachCurrentThread((void**)&env, NULL); if ( ret != JNI_OK ) { return -1; } } else if ( ret < 0 ){ return -1; } } //jarの中身の取得(クラスパスより検索) jclass cls = env->FindClass("jp/co/myCompany/myApp"); //「.」は「/」とみなす。 if (cls == 0) { return -1; } // ↑のクラスからメソッド一覧をgetして認識している。 jmethodID cns = env->GetMethodID(cls, " ", "()V"); if (cns == NULL) { return -1; } jobject obj = env->NewObject(cls, cns); // ■■関数の取得~実行部分 // setParam : URLなど複数のパラメータを一度に設定する。(呼び出し負荷軽減のため) // 注意 : blog用に引数は適当なものに変換。URLとかIDとかそれっぽいのが与えられるわけです。 jmethodID mid = env->GetMethodID(cls, "setParams", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V"); env->CallVoidMethod(obj, mid, env->NewStringUTF(testStr), env->NewStringUTF(testStr2), env->NewStringUTF(testStr3), env->NewStringUTF(testStr4), env->NewStringUTF(testStr5), env->NewStringUTF(testStr6), env->NewStringUTF(testStr7), env->NewStringUTF(testStr8), env->NewStringUTF(testStr9), env->NewStringUTF(testStr10), env->NewStringUTF(testStr11), testInt ); // ■引数検証 : debug用 //mid = env->GetMethodID(cls, "getClassVars", "()Ljava/lang/String;"); //jstring jjj = (jstring)env->CallObjectMethod(obj, mid); //const char* ccc = env->GetStringUTFChars(jjj, NULL); //if (ccc == NULL) { // printf("error"); //} //char *sss = strdup(ccc); //env->ReleaseStringUTFChars(jjj, ccc); // ■実行 mid = env->GetMethodID(cls, "myFunc1", "()I"); int retVal =(int)env->CallIntMethod(obj, mid); return retVal; }
他
JVM破棄も一応あるけど、どうなんだろうか。
今回プロジェクトではそもそも常駐ものなので、考慮しなかった。
// もしjvmを最終的に使い終わったら後始末。 //vm->DestroyJavaVM(); //https://docs.oracle.com/javase/jp/8/docs/technotes/guides/jni/spec/invocation.html#unloading_the_vm //DestroyによるJVMアンロードは未対応です、とのこと。
コメント
コメントを投稿