210 likes | 226 Views
MIDP 拡張の実装に関して. 豊田 陽一 慶應義塾大学 政策・メディア研究科. MIDP リファレンス実装. MIDP の API API は Java 言語による実装 native メソッドは C 言語による実装 エミュレータ C 言語による実装 Wireless Toolkit のエミュレータが Java によって実行されているのに対し、 MIDP のリファレンス実装では 1 つのバイナリコードにコンパイルされる. ビルドの方法. MIDP と CLDC のソースコードが必要
E N D
MIDP拡張の実装に関して 豊田 陽一 慶應義塾大学 政策・メディア研究科
MIDPリファレンス実装 • MIDPのAPI • APIはJava言語による実装 • nativeメソッドはC言語による実装 • エミュレータ • C言語による実装 • Wireless ToolkitのエミュレータがJavaによって実行されているのに対し、MIDPのリファレンス実装では1つのバイナリコードにコンパイルされる
ビルドの方法 • MIDPとCLDCのソースコードが必要 • それぞれのコードを同じディレクトリに展開し、CLDCのソースディレクトリをkvmに変更する • midp1.0.3/build/(ARCH)へ移動し、make • midp1.0.3/build/bin/midpにソースコードからコンパイルされたエミュレータ(KVMを含む)が生成 % ls midp1.0.3fcs/ kvm/ % cd midp1.0.3/build/linux % make BOOTDIR=$JAVA_HOME GCC=true
ソースディレクトリ構成 • midp1.0.3fcs/ • build/(ARCH)/ • プラットフォームごとのmakefileが置いてある • build/share/ • プラットフォームごとのmakefileからインクルードされるmakefileの断片が置いてある
build/share/makefiles • 必要に応じてインクルードされるmakefile群 • Defs.gmk • コンパイルに利用するコマンドへのパスや、コンパイルするソースコード、ソースディレクトリを指定する • KVM.gmk • KVMの部分のソースコードをコンパイルするための設定 • MIDP.gmk • MIDPの部分のソースコードをコンパイルするための設定
主なコンパイルオプション • GCC • コンパイラにgccを利用するかどうか。デフォルトはfalse • BOOTDIR • $(BOOTDIR)/bin/javacなどを利用してJava言語部分のコンパイルを行う • 他にもあるけど実はそれほど気にしなくてもよくって…
Make時のターゲット指定 • Make時にターゲットを指定することによって大まかなビルドオプションは決定できる • debug • デバッグが可能なようにgcc –gオプションをつけてコンパイルしたり、kvmのデバッグ用のコードが有効になる • small • 極力サイズが小さくなるようにビルドを行う。
src/share/classes • MIDPのAPI実装 • Java言語で記述されたソースコードが置いてある • MIDletとかを拡張したり、新しいクラスを定義する場合はここのファイルを書き換えたり、新しく作ったりするといいです
src/share/native • KVMと直接リンクするnativeコード群 • KVMの仕様でインターフェイスだけ定められているものの実装(ex. クラスローダ)や、APIのnativeメソッドの実装がここに置かれる
src/(ARCH)/[classes|native] • プラットフォーム固有のソースコード • とは言え、ほとんどがMIDPのエミュレータのためのコードなので、あまり気にしなくてもいいかも
nativeメソッドを定義する手順 • 以下の2つの手順からなる • Javaコードによるnativeメソッドの宣言 • Cコードによるnativeメソッドの実装 • 関数テーブルの作成 • JNIが利用できないため、nativeコードはKVMに直接リンクされる必要がある
nativeメソッドの宣言 • JNIと同じように宣言できる • メソッドの実体を記述せず、native修飾子をつけるだけ package pear.test; public class NativeTest { public native static void printString(String str, int n); }
nativeメソッドの実装 • KVMのglobal.hをインクルードする • 関数名の命名規則は以下のようになる Java_(パッケージ名)_(パッケージ名)_…_(クラス名)_(メソッド名) • 引数は無く、Javaスタックから引数を取得する • 引数はthis→arg1→…→argNの順番にスタックに積まれていて、ポップするときはこの逆順に得られる。 • 関数は外部から見えるように、extern宣言されている必要がある
nativeメソッドの実装(コード例) #include <global.h> #include <stdio.h> extern Java_pear_test_NativeTest_printString(); void Java_pear_test_NativeTest_printString() { char *s; int i, n; STRING_INSTANCE str; n = popStack(); str = popStackAsType(STRING_INSTANCE); s = getStringContents(str); for(i=0; i<n; i++){ printf(“%02d: %s\n”, i, s); } }
makefileの書き換え • MIDP_DEF_SRC • midpを構成するCのソースコードリスト • Defs.gmkの316行目 • ファイル単位で指定 • MIDP_DEF_SOURCE • midpを構成するjavaのソースコードリスト • Defs.gmkの351行目 • ディレクトリ単位で指定、findで検索
おさらい • nativeメソッドの宣言 • Javaで記述、src/share/classes/以下に保存 • nativeメソッドの実装 • Cで記述、src/share/native/以下に保存 • makefileの編集 • MIDP_DEF_SOURCEにJavaコードのパスを追加 • MIDP_DEF_SRCにCコードのパスを追加 • 心置きなくmake • ターゲットをdebugとかにするとシアワセかも
問題点 • MIDPのバイナリとWireless Toolkit(以下WTK)のemulatorの関係が不明 • WTKのemulatorはシェルスクリプトでJavaのコードを呼び出している • 一方、MIDPのバイナリは完全に一つのプログラム • 基本的には置き換えても問題なく動いている
さらに問題点 • MIDP APIへのクラスパスの相違 • WTKではシェルスクリプト内で明示的に指定 • MIDPではバイナリにリンクしている • WTKから利用したときの問題 • MIDPを拡張したときに、MIDPのバイナリをWTKのktoolbarから利用すると、MIDPの拡張したクラスを見つけてられず、エラー • MIDPを単独で実行したときは問題なく動作
kAWT(xKVM) • 多分、使えないだろうなぁ • 結局、MIDPの部分のソースコードが無いから、いくらPalm対応のKVMのソースコードがあってもビルドできない • 要はMIDP includes KVM • MIDPはただのAPIであるものの、APIはnativeメソッドを含み、KVMではnativeメソッドはJNIが無いためにVMにリンクする必要がある