XP sp3で挑戦
まずMingWをインストールする。
デフォルトのフォルダへ
msysは今回は使わないと思うけどとりあえずインストールgcc-g++は必須のはず。
次にjavaをインストール。
警告はスルー。8.66をインストールした。PATH関係でエラーが出るかもしれないのでいったんログオフ。
次にeclipse CDTのインストール、eclipse.orgへ行ってCDTをダウンロード、ここではeclipse-cpp-mars-1-win32.zipをダウンロードしてC:\に解凍。
起動しようとするとすぐ終了してしまうので、コマンドラインからeclipsec.exeで起動してみる。
メモリーが足りない?eclipse.iniの最後を以下のように書き換えて起動。
1 2 3 |
-Dosgi.requiredJavaVersion=1.7 -Xms256m -Xmx640m |
起動できた。
とりあえずHello World C++というのを作ってみる
メニューから{Project][Build All]
1 2 3 4 5 6 |
07:34:17 **** Rebuild of configuration Debug for project HelloWorld **** Info: Internal Builder is used for build g++ -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\HelloWorld.o" "..\\src\\HelloWorld.cpp" g++ -o HelloWorld.exe "src\\HelloWorld.o" 07:34:22 Build Finished (took 5s.656ms) |
ビルドできた。次に[Run][Run Configuration]で以下のように設定。というか自動で作られる。
[Run][Run]を実行。しかし!!!Hello World!!!が表示されないので、コマンドラインから起動してみると以下のエラーがでた。
リンカオプションに-static-libgcc -static-libstdc++をつけて解決
コンソールを出さないWindowsプログラムを作るため、Makefileプロジェクトを作った。
ソースファイル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <windows.h> extern "C" { int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { MessageBox(NULL, "Hello", "World", 0); return 0; } } |
メイクファイル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
CXXFLAGS = -O2 -g -Wall -fmessage-length=0 -mwindows OBJS = main.o LIBS = TARGET = main.exe $(TARGET): $(OBJS) $(CXX) -static-libgcc -static-libstdc++ -o $(TARGET) $(OBJS) $(LIBS) all: $(TARGET) clean: rm -f $(OBJS) $(TARGET) |
フラグの指定の仕方が強引だがLDFLAGSが効かないみたいなので今はこれで。
これでwin32アプリの準備はできたので、JNIを利用してjavaのランチャーを作る。jni.hがJDKに入ってるので仕方なくJDK7をインストール。
mymain()を作成。http://homepage2.nifty.com/igat/igapyon/diary/2006/ig061108.html からコピペ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
#include "jni.h" int mymain() { JNIEnv *jnienv; JavaVM *javavm; JavaVMInitArgs vm_args; JavaVMOption options[1]; options[0].optionString = "-Djava.class.path=."; vm_args.version = JNI_VERSION_1_2; vm_args.options = options; vm_args.nOptions = 1; vm_args.ignoreUnrecognized = true; int result = JNI_CreateJavaVM(&javavm, (void **)&jnienv, &vm_args); if (result != 0) { return 1; } jclass cls = jnienv->FindClass("MyClass"); if (cls == 0) { return 1; } jmethodID mid = jnienv->GetStaticMethodID(cls, "process", "()Ljava/lang/String;"); if (mid == 0) { return 1; } jobject objResult = jnienv->CallStaticObjectMethod(cls, mid); jthrowable throwResult = jnienv->ExceptionOccurred(); if (throwResult != NULL) { jnienv->ExceptionDescribe(); jnienv->ExceptionClear(); return 1; } if (objResult == NULL) { } else { jstring strResult = (jstring) objResult; printf("[%s]\n", jnienv->GetStringUTFChars(strResult, NULL)); } result = javavm->DestroyJavaVM(); if (result != 0) { return 1; } return 0; } |
メイクファイル修正
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
CXXFLAGS = -O2 -g -Wall -fmessage-length=0 -mwindows -I"C:\Program Files\Java\jdk1.7.0_80\include" -I"C:\Program Files\Java\jdk1.7.0_80\include\win32" OBJS = main.o mymain.o LIBS = LDLIBS = -ljvm TARGET = main.exe $(TARGET): $(OBJS) $(CXX) -static-libgcc -static-libstdc++ -L"C:\Program Files\Java\jdk1.7.0_80\lib" -ljvm -o $(TARGET) $(OBJS) $(LIBS) all: $(TARGET) clean: rm -f $(OBJS) $(TARGET) |
ビルドするとエラー
1 |
undefined reference to `_imp__JNI_CreateJavaVM@12' |
jvm.libがこの関数をエクスポートしてないみたいなので、dllから直接よぶ。今回はjvm.dllの位置は固定でやる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
#include <windows.h> #include "jni.h" typedef jint (JNICALL *FNJNI_CreateJavaVM)(JavaVM **pvm, void **penv, void *args); int mymain() { JNIEnv *jnienv; JavaVM *javavm; JavaVMInitArgs vm_args; JavaVMOption options[1]; options[0].optionString = "-Djava.class.path=."; vm_args.version = JNI_VERSION_1_2; vm_args.options = options; vm_args.nOptions = 1; vm_args.ignoreUnrecognized = true; HMODULE h = LoadLibrary("C:\\Program Files\\Java\\jre1.8.0_66\\bin\\client\\jvm.dll"); if(!h) return 1; FNJNI_CreateJavaVM fn = (FNJNI_CreateJavaVM)GetProcAddress(h, "JNI_CreateJavaVM"); if(!fn) return 1; int result = fn(&javavm, (void **)&jnienv, &vm_args); if (result != 0) { return 1; } jclass cls = jnienv->FindClass("MyClass"); if (cls == 0) { return 1; } jmethodID mid = jnienv->GetStaticMethodID(cls, "process", "()Ljava/lang/String;"); if (mid == 0) { return 1; } jobject objResult = jnienv->CallStaticObjectMethod(cls, mid); jthrowable throwResult = jnienv->ExceptionOccurred(); if (throwResult != NULL) { jnienv->ExceptionDescribe(); jnienv->ExceptionClear(); return 1; } if (objResult == NULL) { } else { jstring strResult = (jstring) objResult; printf("[%s]\n", jnienv->GetStringUTFChars(strResult, NULL)); } result = javavm->DestroyJavaVM(); if (result != 0) { return 1; } return 0; } |
これでVMは作れたのでパラメータを調節すれば動くだろう。
CDTはいろいろくせがあって慣れないと使いづらい。