不合理的网站,seo 论坛,徐州网站制作方法,怎么搜索整个网站JNIEXPORT void JNICALL Java_com_jni_demo_JNIDemo_sayHello (JNIEnv *env, jobject obj){cout}對於這個方法參數中的JNIEnv* env參數的解釋:JNIEnv類型實際上代表了Java環境#xff0c;通過這個JNIEnv* 指針#xff0c;就可以對Java端的代碼進行操作。例如#xff0c;…JNIEXPORT void JNICALL Java_com_jni_demo_JNIDemo_sayHello (JNIEnv *env, jobject obj){cout}對於這個方法參數中的JNIEnv* env參數的解釋:JNIEnv類型實際上代表了Java環境通過這個JNIEnv* 指針就可以對Java端的代碼進行操作。例如創建Java類中的對象調用Java對象的方法獲取Java對象中的屬性等等。JNIEnv的指針會被JNI傳入到本地方法的實現函數中來對Java端的代碼進行操作。JNIEnv類中有很多函數可以用NewObject:創建Java類中的對象NewString:創建Java類中的String對象NewArray:創建類型為Type的數組對象GetField:獲取類型為Type的字段SetField:設置類型為Type的字段的值GetStaticField:獲取類型為Type的static的字段SetStaticField:設置類型為Type的static的字段的值CallMethod:調用返回類型為Type的方法CallStaticMethod:調用返回值類型為Type的static方法等許多的函數具體的可以查看jni.h文件中的函數名稱。參數:jobject obj的解釋:如果native方法不是static的話這個obj就代表這個native方法的類實例如果native方法是static的話這個obj就代表這個native方法的類的class對象實例(static方法不需要類實例的所以就代表這個類的class對象)下面來看一下Java和C中的基本類型的映射關系:為了能夠在C/C中使用Java類jni.h頭文件中專門定義了jclass類型來表示Java中的Class類JNIEnv類中有如下幾個簡單的函數可以取得jclass:jclass FindClass(const char* clsName):通過類的名稱(類的全名這時候包名不是用.號而是用/來區分的)來獲取jclass如: jclass str env-FindClass(java/lang/String);獲取Java中的String對象的class對象。jclass GetObjectClass(jobject obj):通過對象實例來獲取jclass相當於java中的getClass方法jclass GetSuperClass(jclass obj):通過jclass可以獲取其父類的jclass對象在C/C本地代碼中訪問Java端的代碼一個常見的應用就是獲取類的屬性和調用類的方法為了在C/C中表示屬性和方法JNI在jni.h頭文件中定義了jfieldId,jmethodID類型來分別代表Java端的屬性和方法我們在訪問或者設置Java屬性的時候首先就要先在本地代碼取得代表該Java屬性的jfieldID,然后才能在本地代碼中進行Java屬性操作同樣的我們需要呼叫Java端的方法時也是需要取得代表該方法的jmethodID才能進行Java方法調用使用JNIEnv的GetFieldID/GetMethodIDGetStaticFieldID/GetStaticMethodID來取得相應的jfieldID和jmethodID下面來具體看一下這幾個方法GetFieldID(jclass clazz,const char* name,const char* sign)方法的參數說明:clazz:這個簡單就是這個方法依賴的類對象的class對象name:這個是這個字段的名稱sign:這個是這個字段的簽名(我們知道每個變量每個方法都是有簽名的)GetMethodID也能夠取得構造函數的jmethodID,創建一個Java對象時可以調用指定的構造方法這個將在后面向大家介紹:如:env-GetMethodID(data_Class,,()V);下面看一下簽名的格式:通過例子來看一下這些方法的使用packagecom.jni.demo;public classJNIDemo {public int number 0;//定義一個屬性//定義一個本地方法public native voidsayHello();public static voidmain(String[] args){//調用動態鏈接庫System.loadLibrary(JNIDemo);JNIDemo jniDemo newJNIDemo();jniDemo.sayHello();System.out.print(jniDemo.number);}}在來看一下C代碼#include#includecom_jni_demo_JNIDemo.hJNIEXPORTvoid JNICALL Java_com_jni_demo_JNIDemo_sayHello (JNIEnv *env, jobject obj){//獲取obj中對象的class對象jclass clazz env-GetObjectClass(obj);//獲取Java中的number字段的id(最后一個參數是number的簽名)jfieldID id_number env-GetFieldID(clazz,number,I);//獲取number的值jint number env-GetIntField(obj,id_number);//輸出到控制台coutenv-SetIntField(obj,id_number,100L);}編譯成功后在Eclipse運行后的結果:第一個0是在C代碼中的cout第二個100是在Java中的System.out.println(jniDemo.number);JNIEnv提供了眾多的CallMethod和CallStaticMethod還有CallNonvirtualMethod函數需要通過GetMethodID取得相應方法的jmethodID來傳入到上述函數的參數中調用示例方法的三種形式:CallMethod(jobject obj,jmethodID id,....);CallMethod(jobject obj,jmethodID id,va_list lst);CallMethod(jobject obj,jmethodID id,jvalue* v);第一種是最常用的方式第二種是當調用這個函數的時候有一個指向參數表的va_list變量時使用的(很少使用)第三種是當調用這個函數的時候有一個指向jvalue或jvalue數組的指針時用的說明:jvalue在jni.h頭文件中定義是一個union聯合體在C/C中我們知道union是可以存放不同類型的值但是當你給其中一個類型賦值之后這個union就是這種類型了比如你給jvalue中的s賦值的話jvalue就變成了jshort類型了所以我們可以定義一個jvalue數組(這樣就可以包含多種類型的參數了)傳遞到方法中。假如現在Java中有這樣的一個方法:boolean function(int a,double b,char c){........}(1) 在C中使用第一種方式調用function方法:env-CallBooleanMethod(obj , id_function , 10L, 3.4 , La)obj是方法funtion的對象id_function是方法function的id;可以通過GetMethodID()方法獲取然后就是對應的參數這個和Java中的可變參數類似對於最后一個char類型的參數La,為什么前面要加一個L,原因是Java中的字符時Unicode雙字節的而C中的字符時單字節的所以要變成寬字符前面加一個L(2) 在C中使用第三種法師調用function方法:jvalue* args new jvalue[3];//定義jvalue數組args[0].i 10L;//i是jvalue中的jint值args[1].d 3.44;args[2].c La;env-CallBooleanMethod(obj, id_function, args);delete[] args;//是否指針堆內存例子:C中調用Java中的方法:Java代碼public double max(double value1,double value2){return value1value2 ? value1:value2;}JNIEXPORT void JNICALL Java_com_jni_demo_JNIDemo_sayHello (JNIEnv *env, jobject obj){//獲取obj中對象的class對象jclass clazz env-GetObjectClass(obj);//獲取Java中的max方法的id(最后一個參數是max方法的簽名)jmethodID id_max env-GetMethodID(clazz,max,(DD)D);//調用max方法jdouble doubles env-CallDoubleMethod(obj,id_max,1.2,3.4);//輸出返回值cout}C和Java對於繼承后執行的是父類的還是子類的方法是有區別的在Java中所有的方法都是virtual的所以總是調用子類的方法所以CallNonVirtualMethod這個方法就出來了這個方法就可以幫助我們調用Java中的父類的方法在JNI中定義的CallNonvirtualMethod就能夠實現子類對象調用父類方法的功能如果想要調用一個對象的父類方法而不是子類的方法的話就可以使用CallNonvirtualMethod了要使用它首先要獲得父類及其要調用的父類方法的jmethodID,然后傳入到這個函數就能通過子類對象調用被覆寫的父類的方法了例子在Java中定義Father類:packagecom.jni.demo;public classFather {public voidfunction(){System.out.println(Father:function);}}在定義一個子類Child:繼承Father類從寫父類中的function方法packagecom.jni.demo;public class Child extendsFather{Overridepublic voidfunction(){System.out.println(Child:function);}}在JNIDemo代碼:定義Father類型的屬性packagecom.jni.demo;public classJNIDemo {public Father father newChild();//定義一個本地方法public native voidsayHello();public static voidmain(String[] args){//調用動態鏈接庫System.loadLibrary(JNIDemo);JNIDemo jniDemo newJNIDemo();jniDemo.sayHello();}}在來看一下C中的代碼#include#includecom_jni_demo_JNIDemo.hJNIEXPORTvoid JNICALL Java_com_jni_demo_JNIDemo_sayHello (JNIEnv *env, jobject obj){//獲取obj中對象的class對象jclass clazz env-GetObjectClass(obj);//獲取Java中的father字段的id(最后一個參數是father字段的簽名)jfieldID id_father env-GetFieldID(clazz,father,Lcom/jni/demo/Father;);//獲取father字段的對象類型jobject father env-GetObjectField(obj,id_father);//獲取father對象的class對象jclass clazz_father env-FindClass(com/jni/demo/Father);//獲取father對象中的function方法的idjmethodID id_father_function env-GetMethodID(clazz_father,function,()V);//調用父類中的function方法(但是會執行子類的方法)env-CallVoidMethod(father,id_father_function);//調用父類中的function方法(執行就是父類中的function方法)env-CallNonvirtualVoidMethod(father,clazz_father,id_father_function);}Child:function是調用env-CallVoidMethod(...)方法的Father:function是調用env-CallNonvirtualMethod(...)方法的這樣就能夠控制到底調用哪個類的function方法了。