android jni 中jnienv,android JNI中JNIEnv類型和jobject類型的解釋

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++中的基本類型的映射關系:

db084067a1d553406db58b5e54d4eb9d.png

為了能夠在C/C++中使用Java類,jni.h頭文件中專門定義了jclass類型來表示Java中的Class類

JNIEnv類中有如下幾個簡單的函數可以取得jclass:

fb2d097eff351d8b8c3c63ba4c605df9.gif

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對象

fb2d097eff351d8b8c3c63ba4c605df9.gif

在C/C++本地代碼中訪問Java端的代碼,一個常見的應用就是獲取類的屬性和調用類的方法,為了在C/C++中表示屬性和方法,JNI在jni.h頭文件中定義了jfieldId,jmethodID類型來分別代表Java端的屬性和方法

我們在訪問,或者設置Java屬性的時候,首先就要先在本地代碼取得代表該Java屬性的jfieldID,然后才能在本地代碼中進行Java屬性操作,同樣的,我們需要呼叫Java端的方法時,也是需要取得代表該方法的jmethodID才能進行Java方法調用

使用JNIEnv的:

GetFieldID/GetMethodID

GetStaticFieldID/GetStaticMethodID

來取得相應的jfieldID和jmethodID

下面來具體看一下這幾個方法:

GetFieldID(jclass clazz,const char* name,const char* sign)

方法的參數說明:

clazz:這個簡單就是這個方法依賴的類對象的class對象

name:這個是這個字段的名稱

sign:這個是這個字段的簽名(我們知道每個變量,每個方法都是有簽名的)

GetMethodID也能夠取得構造函數的jmethodID,創建一個Java對象時可以調用指定的構造方法,這個將在后面向大家介紹:

如:env->GetMethodID(data_Class,"","()V");

13ded53bcef7d1dd402f3abe5200cf71.bmp

下面看一下簽名的格式:

6439fd838abe8779982ea523c468b83c.png

通過例子來看一下這些方法的使用

fb2d097eff351d8b8c3c63ba4c605df9.gif

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);

}

}

fb2d097eff351d8b8c3c63ba4c605df9.gif

在來看一下C++代碼:

fb2d097eff351d8b8c3c63ba4c605df9.gif

#include#include"com_jni_demo_JNIDemo.h"JNIEXPORTvoid 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);//輸出到控制臺

cout<

env->SetIntField(obj,id_number,100L);

}

fb2d097eff351d8b8c3c63ba4c605df9.gif

編譯成功后,在Eclipse運行后的結果:

216083576cc2d0571bc5092e1ab1077a.png

第一個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數組(這樣就可以包含多種類型的參數了)傳遞到方法中。

e86ef18b585d630356c2c9f912ff147d.png

假如現在Java中有這樣的一個方法:

boolean function(int a,double b,char c)

{

........

}

(1) 在C++中使用第一種方式調用function方法:

env->CallBooleanMethod(obj , id_function , 10L, 3.4 , L'a')

obj是方法funtion的對象

id_function是方法function的id;可以通過GetMethodID()方法獲取

然后就是對應的參數,這個和Java中的可變參數類似,對於最后一個char類型的參數L'a',為什么前面要加一個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 = L'a';

env->CallBooleanMethod(obj, id_function, args);

delete[] args;//是否指針堆內存

例子:C++中調用Java中的方法:

Java代碼:

public double max(double value1,double value2){

return value1>value2 ? value1:value2;

}

fb2d097eff351d8b8c3c63ba4c605df9.gif

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<

}

fb2d097eff351d8b8c3c63ba4c605df9.gif

C++和Java對於繼承后執行的是父類的還是子類的方法是有區別的,在Java中所有的方法都是virtual的,所以總是調用子類的方法,所以CallNonVirtualMethod這個方法就出來了,這個方法就可以幫助我們調用Java中的父類的方法:

在JNI中定義的CallNonvirtualMethod就能夠實現子類對象調用父類方法的功能,如果想要調用一個對象的父類方法,而不是子類的方法的話,就可以使用CallNonvirtualMethod了,要使用它,首先要獲得父類及其要調用的父類方法的jmethodID,然后傳入到這個函數就能通過子類對象調用被覆寫的父類的方法了

例子:在Java中定義Father類:

fb2d097eff351d8b8c3c63ba4c605df9.gif

packagecom.jni.demo;public classFather {public voidfunction(){

System.out.println("Father:function");

}

}

fb2d097eff351d8b8c3c63ba4c605df9.gif

在定義一個子類Child:繼承Father類,從寫父類中的function方法

fb2d097eff351d8b8c3c63ba4c605df9.gif

packagecom.jni.demo;public class Child extendsFather{

@Overridepublic voidfunction(){

System.out.println("Child:function");

}

}

fb2d097eff351d8b8c3c63ba4c605df9.gif

在JNIDemo代碼:定義Father類型的屬性

fb2d097eff351d8b8c3c63ba4c605df9.gif

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();

}

}

fb2d097eff351d8b8c3c63ba4c605df9.gif

在來看一下C++中的代碼:

fb2d097eff351d8b8c3c63ba4c605df9.gif

#include#include"com_jni_demo_JNIDemo.h"JNIEXPORTvoid 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方法的id

jmethodID 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);

}

fb2d097eff351d8b8c3c63ba4c605df9.gif

Child:function是調用env->CallVoidMethod(...)方法的

Father:function是調用env->CallNonvirtualMethod(...)方法的

這樣就能夠控制到底調用哪個類的function方法了。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/529096.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/529096.shtml
英文地址,請注明出處:http://en.pswp.cn/news/529096.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

yang模型中rpc_領域驅動模型(DDD)設計講解

一. 什么是領域驅動模型(DDD)&#xff1f;領域驅動模型一種設計思想&#xff0c;我們又稱為DDD設計思想。是一種為了解決傳統設計思想帶來的維護困難&#xff0c;溝通困難和交互困難而產生的一種新的思想。也解決了在部分公司中&#xff0c;一個項目組就是一套服務&#xff0c;…

鴻蒙系統操作界面跟蘋果很像,鴻蒙手機UI界面曝出!圖標擬物化、操作邏輯近似蘋果iOS13...

原標題&#xff1a;鴻蒙手機UI界面曝出&#xff01;圖標擬物化、操作邏輯近似蘋果iOS13?【IT爆料王-原創文章-具備版權效力】就在近日&#xff0c;筆者收到了網友的匿名私信&#xff0c;提供給筆者華為鴻蒙系統的UI界面截圖&#xff0c;以及搭載鴻蒙系統的華為手機的曝光圖片。…

python3中的int類型占64位,有沒有什么辦法來強制Python來使用64位整數的Windows?

I’ve noticed that whenever any integer surpasses 2^31-1 my number heavy code suffers a large slowdown, despite the fact I’m using a 64 bit build of Python on a 64bit version of Windows. This seems to be true on Python 2.7 and Python 3. I’ve read that Wi…

crtsiii型無砟軌道板_無砟軌道裂縫破損怎么修補

隨著高速鐵路、客運專線、城市地鐵的快速發展&#xff0c;無砟軌道軌道板&#xff08;道床板&#xff09;廣泛應用&#xff0c;但施工中和運營期都發現軌道板混凝土存在不同程度的微細裂縫&#xff0c;對無砟軌道造成了一定的病害。高鐵軌道板裂縫是不可避免的。為確保無砟軌道…

c調用python第三方庫_Python使用ctypes模塊調用DLL函數之C語言數組與numpy數組傳遞...

在Python語言中&#xff0c;可以使用ctypes模塊調用其它如C語言編寫的動態鏈接庫DLL文件中的函數&#xff0c;在提高軟件運行效率的同時&#xff0c;也可以充分利用目前市面上各種第三方的DLL庫函數&#xff0c;以擴充Python軟件的功能及應用領域&#xff0c;減少重復編寫代碼、…

妲己機器人怎么升級固件_臺灣重金設計的3D妲己,亮瞎了

大家還記得前幾天米醋分享的國內首檔二次元選秀&#xff0c;遭網友瘋狂吐槽&#xff1a;不知道怎么形容的丑&#xff01;當米醋看到了這檔綜藝的宣傳海報時瞬間被這一批選手的顏值所吸引&#xff01;太魔幻了&#xff01;沒成想看到3D人物效果時米醋卻被這盛世丑顏丑到裂開&…

go語言通道插入0_Go語言入門必知教程-通道

Golang提供了一種稱為通道的機制&#xff0c;用于在協程之間共享數據。當函數作為協程執行并發活動時&#xff0c;需要它們共享資源或數據&#xff0c;通道便充當協程之間的管道(管道)&#xff0c;提供一種確保同步交換數據的機制。需要在聲明通道時指定數據類型&#xff0c;可…

aes加密字符串c++_springboot2.2.X手冊:防抓包?快速實現API接口數據加密

溪云閣&#xff1a;專注編程教學&#xff0c;架構&#xff0c;JAVA&#xff0c;Python&#xff0c;微服務&#xff0c;機器學習等&#xff0c;歡迎關注上一篇&#xff1a;springboot2.2.X手冊&#xff1a;redis的7種類型100個方法全解析有沒有遇到這樣子的接口&#xff0c;放到…

鴻蒙系統打造完備終端,搭載鴻蒙系統的手機很快推出,華為生態更加完善

2019年的8月9日&#xff0c;在華為開發者大會上華為向大家正式的發布了一款操作系統——鴻蒙系統。這個系統備受大家的關注&#xff0c;鴻蒙2.0的發布也在時刻期待中。因為在目前的操作系統中&#xff0c;華為的鴻蒙操作系統是僅次于安卓、ios的存在&#xff0c;而今日&#xf…

curl socket 訪問_使用Curl、socket、file_get_contents三種方法POST提交數據 | 學步園

# <?php # /**# * Socket版本# * 使用方法&#xff1a;# * $post_string "appsocket&versionbeta";# * request_by_socket(facebook.cn,/restServer.php,$post_string);# */# function request_by_socket($remote_server,$remote_path,$post_string,$port …

html 標簽 r語言,從R中的字符串中刪除html標簽

我正在嘗試將網頁源代碼讀入R并將其作為字符串處理。我正在嘗試刪除段落并從段落文本中刪除html標簽。我遇到了以下問題&#xff1a;我嘗試實現一個功能來刪除html標簽&#xff1a;cleanFunfunction(fullStr){#find location of tags and citationstagLoccbind(str_locate_all(…

python給圖片加半透明水印_Python 批量加水印就這么簡單!

工作的時候&#xff0c;尤其是自媒體&#xff0c;我們必備水印添加工具以保護我們的知識產權,網上有許多的在線/下載的水印添加工具&#xff0c;但他們或多或少都存在以下問題&#xff1a; 在線工具需要將圖片上傳到對方服務器&#xff0c;信息不安全。 很多工具不具備批量處理…

html 選中狀態,html默認選中狀態

html中標簽用法解析及如何設置selec標簽定義和用法 select 元素可創建單選或多選菜單。當提交表單時&#xff0c;瀏覽器會提交選定的項目&#xff0c;或者收集用逗號分隔的多個選項&#xff0c;將其合成一個單獨的參數列表&#xff0c;并且在將 表單數據提交給服務器時包括 nam…

nemesis什么車_nemesis是什么意思_nemesis的翻譯_音標_讀音_用法_例句_愛詞霸在線詞典...

全部報應Was he aiming at Bryant, his old nemesis and a favorite target in the past?他是不是暗指科比, 一直的“競爭對手”和過去最中意的目標?期刊摘選After the defeat of their old arch nemesis, the Turtle have grown apart as a family.在擊敗舊時強敵后, 忍者神…

wxpython制作表格界面_[Python] wxPython 菜單欄控件學習總結(原創)

1、總結 1、大體創建過程 1、創建一個 菜單欄 : menuBar wx.MenuBar()相當于這個白色地方&#xff0c;沒有File這個菜單 2、創建 菜單 : fileMenu wx.Menu()這兩個不是直接“用的”&#xff0c;叫菜單。既用來分類其他 菜單項 的文件夾樣 3、創建 菜單項 : newItem wx.MenuI…

android 8三星note8,信息太多很煩瑣?告訴你三星Note8有妙招

不知從何時開始&#xff0c;我們眼前的信息變得豐富而繁雜。簡潔的新聞無需經過報紙過濾&#xff0c;發生數分鐘已經城皆知。預測晴雨也無需依靠天氣先生&#xff0c;點亮手機即可洞悉風雨。生活在信息時代的我們僅用幾英寸的窗口觀察世界&#xff0c;信息的洪流難免會遮蔽眼前…

realloc函_realloc(重新分配內存空間的函數)

在頭文件中定義void * realloc(void * ptr&#xff0c;size_t new_size);重新分配給定的內存區域。它必須預先分配malloc()&#xff0c;calloc()或realloc()尚未釋放與free或呼叫realloc。否則&#xff0c;結果是不確定的。重新分配由以下兩者之一完成&#xff1a;a)ptr如有可能…

python做excel表格教程視頻_基于Python實現excel表格讀寫

首先安裝對應的xlrd和xlwt 打開cmd命令窗口輸入pip install xlrd和pip install xlwt就可以安裝。之后輸入pip list檢查是否成功配置&#xff1a;xlrd操作# 接下來就是常用的語法操作&#xff1a; excel_data xlrd.open_workbook(文件路徑)#得到對應的工作表 sheet excel_data…

虛無鴻蒙哪個厲害,【圖說鴻蒙】鴻蒙設定之七柱神(五)

原標題&#xff1a;【圖說鴻蒙】鴻蒙設定之七柱神(五)七柱神玄冥神飛來流去本無心&#xff0c;無空無我混天塵。幻作人形深簡出&#xff0c;不是老嫗是海神。玄冥神 虛無荒海司掌海洋、流動之力 神威之色為藍執掌海洋、流動之力的神&#xff0c;是神道“熵”的最高掌控者&#…

java lambda 排序_Java8特性:Lambda表達式之概念篇

Java自誕生已經有十幾個年頭了&#xff0c;目前也已經發布了第十三個大版本&#xff0c;其中Java8是常用的版本中最新的一個版本。而Java8最大的特性就是&#xff1a;Lambda表達式、函數式接口和Stream流。本篇我只介紹Lamda表達式的概念以及簡單使用&#xff0c;至于別的我打算…