はじめに
前回では、android側からタッチ反応を発生してから、jniを通して変換エンジンのnative側が候補を返すまでを説明した。
今回ではjni部分のコードを少し説明する。
What is jni?
言わばjavaとc, cppとの間のインターフェイスですね。cやcppを使って、java側とデータのやり取りができる。
Java Native Interface
mozcに使われているjni
java側ではMozcJNI.javaというラッパーがある。メソッドはこの通り。
load(String, Buffer, Buffer, String)
初期化用のメソッド、apkの中に入っている辞書データなどをnative側に渡す
evalCommand(byte[])
native側と通信するメソッド、jniで実装
onPostLoad(String, Buffer, Buffer)
loadメソッドに使われている、jniで実装
getVersion()
native側のバージョン情報をjava側に渡す。loadメソッドに使われている、jniで実装
jniの実装ファイルはjni/mozcjni.cc。では、evalCommand(byte[])
を詳しく見てみよう。
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
| // ------> この矢印のあたりは、私の追加したコメントです
jbyteArray JNICALL evalCommand(JNIEnv *env, jclass clazz, jbyteArray in_bytes_array) {
jboolean is_copy = false;
jbyte *in_bytes = env->GetByteArrayElements(in_bytes_array, &is_copy);
const jsize in_size = env->GetArrayLength(in_bytes_array);
// ------> commandにパースする。session/commands.protoにはcommandの定義が書かれいる。
// ------> protobuf(Protocol Buffers)というライブラリを使っています。
mozc::commands::Command command;
command.ParseFromArray(in_bytes, in_size);
// ------> native側でcommandを処理する。結果はcommandの中に格納する。
mozc::Singleton<SessionHandlerSingletonAdapter>::get()->getHandler()
->EvalCommand(&command);
// Use JNI_ABORT because in_bytes is read only.
// ------> JNI_ABORT: 要素列をJava配列に反映させず、要素列バッファを解放する。
env->ReleaseByteArrayElements(in_bytes_array, in_bytes, JNI_ABORT);
// 変換結果はjbyteArrayとしてjava側に返す
const int out_size = command.ByteSize();
jbyteArray out_bytes_array = env->NewByteArray(out_size);
// ------> is_copy: 0の場合、生成された配列(out_bytes)を変更すると、java側にも変更される。
// 1の場合、変更してもjava側には変更されない。
jbyte *out_bytes = env->GetByteArrayElements(out_bytes_array, &is_copy);
command.SerializeToArray(out_bytes, out_size);
// Use 0 to copy out_bytes to out_bytes_array.
// ------> 0の場合、要素列をJava配列に反映させ、要素列バッファを解放する。
env->ReleaseByteArrayElements(out_bytes_array, out_bytes, 0);
return out_bytes_array;
}
|
in_bytes_array
には、タッチされたキーの情報などが入っている。
out_bytes_array
には、変換候補などが入っている。
前回最後のlog部分を参考してくだい。
終わりに
jni側の実装に関する説明はここまで。
次回ではevalCommand
メソッドをもっと細かく説明する。