其中 JNI 在呼叫 Java 物件時,Java 八大型態及 Java Class 型態在 JNI 中採用的關鍵字:
Java boolean type => "Z"
Java byte type => "B"
Java char type => "C"
Java short type => "S"
Java int type => "I"
Java long type => "J"
Java float type => "F"
Java double type => "D"
Java object type => "Ljava/lang/Object;"
Java Array of int type => "[I"
Java Array of double type => "[D"
Java Array of java/lang/Object type => "[Ljava/lang/Object;"
舉例來說,以 Vector 的 public boolean add(E e) 函數為例:
jclass vectorClass = env->FindClass("java.util.Vector");
jmethodID vector_add = env->GetMethodID(vectorClass, "add", "(Ljava/lang/Object;)Z");
其中 "(Ljava/lang/Object;)Z" 代表此函式回傳為 boolean 型態,而需要傳遞一個 java/lang/Object 當作參數。
最後是比較冗長的操作:
Java code:
static {
System.loadLibrary("test")
}
public native boolean test(Vector<HashMap<String, String>> obj);
void usage() {
Vector<HashMap<String, String>> output = new Vector<HashMap<String, String>>();
boolean ret = test(output);
Log.i(tag, "Ret: "+ret+", output size: "+output.size());
}
build.gradle (Module:app):
android.ndk {
moduleName = "test"
ldLibs.addAll(["log"])
CFlags.add("-std=c++11")
stl = "c++_shared"
}
C/C++ code:
#include <jni.h>
#include <android/log.h>
#define LOG_TAG "JNI"
#define LOGV(...)__android_log_print( ANDROID_LOG_VERBOSE,LOG_TAG, __VA_ARGS__ )
#define LOGD(...)__android_log_print( ANDROID_LOG_DEBUG,LOG_TAG, __VA_ARGS__ )
#define LOGI(...)__android_log_print( ANDROID_LOG_INFO,LOG_TAG, __VA_ARGS__ )
#define LOGW(...)__android_log_print( ANDROID_LOG_WARN,LOG_TAG, __VA_ARGS__ )
#define LOGE(...)__android_log_print( ANDROID_LOG_ERROR,LOG_TAG, __VA_ARGS__ )
extern "C" {
jboolean Java_YourPackageName_test(JNIEnv *env, jobject thiz, jobject vectorObject) {
jclass vectorClass = env->GetObjectClass(vectorObject);
jmethodID vector_size = env->GetMethodID(vectorClass, "size", "()I");
jmethodID vector_add = env->GetMethodID(vectorClass, "add", "(Ljava/lang/Object;)Z");
jmethodID vector_elementAt = env->GetMethodID(vectorClass, "elementAt", "(I)Ljava/lang/Object;");
jclass hashMapClass = env->FindClass("java/util/HashMap");
jmethodID hashMap_init = env->GetMethodID(hashMapClass, "<init>", "(I)V");
jmethodID hashMap_put = env->GetMethodID(hashMapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
jmethodID hashMap_get = env->GetMethodID(hashMapClass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
jmethodID hashMap_size = env->GetMethodID(hashMapClass, "size", "()I");
std::unordered_map<int, std::string> attrs;
attrs[0] = "Hello";
attrs[1] = "World";
if (vectorObject && vectorClass && hashMapClass) {
// init HashMap object
jobject dataHashMap = env->NewObject(hashMapClass, hashMap_init, 1);
for (auto it = attrs.begin(); it != attrs.end(); ++it) {
jstring key = env->NewStringUTF(std::to_string(it->first).c_str());
jstring value = env->NewStringUTF(it->second.c_str());
env->CallObjectMethod(dataHashMap, hashMap_put, key, value);
env->DeleteLocalRef(key);
env->DeleteLocalRef(value);
}
LOGI("hashmap size: %d", env->CallIntMethod(dataHashMap, hashMap_size));
LOGI("vector size: %d", env->CallIntMethod(vectorObject, vector_size));
// vector add
env->CallBooleanMethod(vectorObject, vector_add, dataHashMap);
env->DeleteLocalRef(dataHashMap);
// access vector
for (int i=0, cnt = env->CallIntMethod(vectorObject, vector_size) ; i<cnt; ++i) {
LOGI("get vector_elementAt: %d", i);
if (vector_elementAt) {
jobject dataInVector = env->CallObjectMethod(vectorObject, vector_elementAt, i);
jclass dataInVectorClass = env->GetObjectClass(dataInVector);
jmethodID dataInVector_get = env->GetMethodID(dataInVectorClass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
if (dataInVector && dataInVector_get) {
jstring key = env->NewStringUTF(std::to_string(0).c_str());
jstring value = (jstring)env->CallObjectMethod(dataInVector, dataInVector_get, key);
LOGI("get vector_elementAt: %d, value: [%s]", i, value);
env->DeleteLocalRef(key);
}
}
}
}
return false;
}
}
沒有留言:
張貼留言