經過使用合適的JNI函數,你能夠建立Java對象,get、set 靜態(static)和 實例(instance)的域,調用靜態(static)和實例(instance)函數。JNI經過ID識別域和方法,一個域或方法的ID是任何處理域和方法的函數的必須參數。
下表列出了用以獲得靜態(static)和實例(instance)的域與方法的JNI函數。每一個函數接受(做爲參數)域或方法的類,它們的名稱,符號和它們對應返回的jfieldID或jmethodID。 java
函數 | 描述 |
GetFieldID | 獲得一個實例的域的ID |
GetStaticFieldID | 獲得一個靜態的域的ID |
GetMethodID | 獲得一個實例的方法的ID |
GetStaticMethodID | 獲得一個靜態方法的ID |
構造一個Java對象的實例 android
jclass cls = (*env)->FindClass(env, "Lpackagename/classname;"); //建立一個class的引用 jmethodID id = (*env)->GetMethodID(env, cls, "", "(D)V"); //注意這裏方法的名稱是"",它表示這是一個構造函數,並且構造參數是double型的 jobject obj = (*env)->NewObjectA(env, cls, id, args); //得到一實例,args是構造函數的參數,它是一個jvalue*類型。
首先是得到一個Java類的class引用 (*env)->FindClass(env, "Lpackagename/classname;"); 請注意參數:Lpackagename/classname; ,L表明這是在描述一個對象類型,packagename/classname是該對象耳朵class路徑,請注意必定要以分號(;)結束! c++
而後是獲取函數的id,jmethodID id = env->GetMethodID(cls, "", "(D)V"); 第一個是剛剛得到的class引用,第二個是方法的名稱,最後一個就是方法的簽名了 數組
仍是不懂?我曾經如此,請接着看... 函數
JNINativeMethod的定義以下: spa
typedef struct { const char* name; const char* signature; void* fnPtr; } JNINativeMethod;第一個變量name是Java中函數的名字。
其中比較難以理解的是第二個參數,例如
"()V"
"(II)V"
"(Ljava/lang/String;Ljava/lang/String;)V" 指針
實際上這些字符是與函數的參數類型一一對應的。
"()" 中的字符表示參數,後面的則表明返回值。例如"()V" 就表示void Func();
"(II)V" 表示 void Func(int, int); code
類型
|
符號 |
boolean | Z |
byte | B |
char | C |
short | S |
int | I |
long | L |
float | F |
double | D |
void | V |
object對象 | LClassName; L類名; |
Arrays |
[array-type [數組類型
|
methods方法 | (argument-types)return-type (參數類型)返回類型 |
稍稍補充一下: 對象
一、方法參數或者返回值爲java中的對象時,簽名中必須以「L」加上其路徑,不過此路徑必須以「/」分開,自定義的對象也使用本規則 內存
好比說 java.lang.String爲「java/lang/String」,com.nedu.jni.helloword.Student爲"Lcom /nedu/jni/helloword/Student;"
二、方法參數或者返回值爲數組類型時,請前加上[
例如[I表示 int[],[[[D表示 double[][][],即幾維數組就加幾個[
jclass cls = (*env)->GetObjectClass(env, obj); // 使用GetObjectClass方法獲取obj對應的jclass。 jclass cls = (*env)->FindClass(「android/util/log」) // 直接搜索類名,須要是static修飾的類。
jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V"); //GetStaticMethodID(…),獲取靜態方法的ID使用GetMethdoID方法獲取你要使用的方法的MethdoID其參數的意義:
(*env)->CallVoidMethod(env, obj, mid, depth);// CallStaticIntMethod(….) , 調用靜態方法使用CallVoidMethod方法調用方法。參數的意義:
注:這裏使用的是CallVoidMethod方法調用,由於沒有返回值,若是有返回值的話使用對應的方法,在後面會提到。
CallVoidMethod CallStaticVoidMethod CallIntMethod CallStaticVoidMethod CallBooleanMethod CallStaticVoidMethod CallByteMethod CallStaticVoidMethod
如今稍稍明白文章開始構造Java對象那個實例了吧?讓咱們繼續深刻一下:
從java程序中傳過去的String對象在本地方法中對應的是jstring類型,jstring類型和c中的char*不一樣,因此若是你直接當作char*使用的話,就會出錯。所以在使用以前須要將jstring轉換成爲c/c++中的char*,這裏使用JNIEnv提供的方法轉換。
const char *str = (*env)->GetStringUTFChars(env, jstr, 0); (*env)->ReleaseStringUTFChars(env, jstr, str);
這裏使用GetStringUTFChars方法將傳進來的prompt(jstring類型)轉換成爲UTF-8的格式,就可以在本地方法中使用了。
注意:在使用完你所轉換以後的對象以後,須要顯示調用ReleaseStringUTFChars方法,讓JVM釋放轉換成UTF-8的string的對象的空間,若是不顯示的調用的話,JVM中會一直保存該對象,不會被垃圾回收器回收,所以就會致使內存溢出。
下面是Jni訪問String對象的一些方法:
下面提供兩個String對象和char*互轉的方法:
/* c/c++ string turn to java jstring */ jstring charToJstring(JNIEnv* env, const char* pat) { jclass strClass = (*env)->FindClass(env, "java/lang/String"); jmethodID ctorID = (*env)->GetMethodID(env, strClass, "", "([BLjava/lang/String;)V"); jbyteArray bytes = (*env)->NewByteArray(env, strlen(pat)); (*env)->SetByteArrayRegion(env, bytes, 0, strlen(pat), (jbyte*)pat); jstring encoding = (*env)->NewStringUTF(env, "UTF-8"); return (jstring)(*env)->NewObject(env, strClass, ctorID, bytes, encoding); } /* java jstring turn to c/c++ char* */ char* jstringToChar(JNIEnv* env, jstring jstr) { char* pStr = NULL; jclass jstrObj = (*env)->FindClass(env, "java/lang/String"); jstring encode = (*env)->NewStringUTF(env, "utf-8"); jmethodID methodId = (*env)->GetMethodID(env, jstrObj, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray byteArray = (jbyteArray)(*env)->CallObjectMethod(env, jstr, methodId, encode); jsize strLen = (*env)->GetArrayLength(env, byteArray); jbyte *jBuf = (*env)->GetByteArrayElements(env, byteArray, JNI_FALSE); if (jBuf > 0) { pStr = (char*)malloc(strLen + 1); if (!pStr) { return NULL; } memcpy(pStr, jBuf, strLen); pStr[strLen] = 0; } env->ReleaseByteArrayElements(byteArray, jBuf, 0); return pStr; }
本文轉自Zhiweiofli's Blog,轉載請註明出處,謝謝。