日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

android jni 调用java对象_Android NDK开发之Jni调用Java对象

發(fā)布時(shí)間:2024/9/27 Android 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android jni 调用java对象_Android NDK开发之Jni调用Java对象 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本地代碼中使用Java對(duì)象

通過(guò)使用合適的JNI函數(shù),你可以創(chuàng)建Java對(duì)象,get、set 靜態(tài)(static)和 實(shí)例(instance)的域,調(diào)用靜態(tài)(static)和實(shí)例(instance)函數(shù)。JNI通過(guò)ID識(shí)別域和方法,一個(gè)域或方法的ID是任何處理域和方法的函數(shù)的必須參數(shù)。

下表列出了用以得到靜態(tài)(static)和實(shí)例(instance)的域與方法的JNI函數(shù)。每個(gè)函數(shù)接受(作為參數(shù))域或方法的類(lèi),它們的名稱(chēng),符號(hào)和它們對(duì)應(yīng)返回的jfieldID或jmethodID。

函數(shù)

描述

GetFieldID

得到一個(gè)實(shí)例的域的ID

GetStaticFieldID

得到一個(gè)靜態(tài)的域的ID

GetMethodID

得到一個(gè)實(shí)例的方法的ID

GetStaticMethodID

得到一個(gè)靜態(tài)方法的ID

構(gòu)造一個(gè)Java對(duì)象的實(shí)例

C代碼??

jclass?cls?=?(*env)->FindClass(env,?"Lpackagename/classname;");??//創(chuàng)建一個(gè)class的引用

jmethodID?id?=?(*env)->GetMethodID(env,?cls,?"",?"(D)V");??//注意這里方法的名稱(chēng)是"",它表示這是一個(gè)構(gòu)造函數(shù),而且構(gòu)造參數(shù)是double型的

jobject?obj?=?(*env)->NewObjectA(env,?cls,?id,?args);??//獲得一實(shí)例,args是構(gòu)造函數(shù)的參數(shù),它是一個(gè)jvalue*類(lèi)型。

首先是獲得一個(gè)Java類(lèi)的class引用?(*env)->FindClass(env, "Lpackagename/classname;"); ?請(qǐng)注意參數(shù):Lpackagename/classname;,L代表這是在描述一個(gè)對(duì)象類(lèi)型,packagename/classname是該對(duì)象耳朵class路徑,請(qǐng)注意一定要以分號(hào)(;)結(jié)束!

然后是獲取函數(shù)的id,jmethodID id = env->GetMethodID(cls, "", "(D)V");? 第一個(gè)是剛剛獲得的class引用,第二個(gè)是方法的名稱(chēng),最后一個(gè)就是方法的簽名了

還是不懂?我曾經(jīng)如此,請(qǐng)接著看...

難理解的函數(shù)簽名

JNINativeMethod的定義如下:

typedef struct{const char*name;const char*signature;void*fnPtr;

} JNINativeMethod;

第一個(gè)變量name是Java中函數(shù)的名字。

第二個(gè)變量signature,用字符串是描述了函數(shù)的參數(shù)和返回值

第三個(gè)變量fnPtr是函數(shù)指針,指向C函數(shù)。

其中比較難以理解的是第二個(gè)參數(shù),例如

"()V"

"(II)V"

"(Ljava/lang/String;Ljava/lang/String;)V"

實(shí)際上這些字符是與函數(shù)的參數(shù)類(lèi)型一一對(duì)應(yīng)的。

"()" 中的字符表示參數(shù),后面的則代表返回值。例如"()V" 就表示void Func();

"(II)V" 表示 void Func(int, int);

那其他情況呢?請(qǐng)查看下表:

類(lèi)型

符號(hào)

boolean

Z

byte

B

char

C

short

S

int

I

long

L

float

F

double

D

void

V

object對(duì)象

LClassName; ? ? ?L類(lèi)名;

Arrays

[array-type ? ? ? ?[數(shù)組類(lèi)型

methods方法

(argument-types)return-type ? ? (參數(shù)類(lèi)型)返回類(lèi)型

稍稍補(bǔ)充一下:

1、方法參數(shù)或者返回值為java中的對(duì)象時(shí),簽名中必須以“L”加上其路徑,不過(guò)此路徑必須以“/”分開(kāi),自定義的對(duì)象也使用本規(guī)則

比如說(shuō) java.lang.String為“java/lang/String”,com.nedu.jni.helloword.Student為"Lcom /nedu/jni/helloword/Student;"

2、方法參數(shù)或者返回值為數(shù)組類(lèi)型時(shí),請(qǐng)前加上[

例如[I表示 int[],[[[D表示 double[][][],即幾維數(shù)組就加幾個(gè)[

在本地方法中調(diào)用Java對(duì)象的方法

1、獲取你需要訪問(wèn)的Java對(duì)象的類(lèi):

jclass cls = (*env)->GetObjectClass(env, obj); //使用GetObjectClass方法獲取obj對(duì)應(yīng)的jclass。

jclass cls = (*env)->FindClass(“android/util/log”) //直接搜索類(lèi)名,需要是static修飾的類(lèi)。

2、獲取MethodID:

jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V"); //GetStaticMethodID(…),獲取靜態(tài)方法的ID使用GetMethdoID方法獲取你要使用的方法的MethdoID

使用CallVoidMethod方法調(diào)用方法。參數(shù)的意義:

env-->JNIEnv

obj-->通過(guò)本地方法穿過(guò)來(lái)的jobject

mid-->要調(diào)用的MethodID(即第二步獲得的MethodID)

depth-->方法需要的參數(shù)(對(duì)應(yīng)方法的需求,添加相應(yīng)的參數(shù))

注:這里使用的是CallVoidMethod方法調(diào)用,因?yàn)闆](méi)有返回值,如果有返回值的話使用對(duì)應(yīng)的方法,在后面會(huì)提到。

CallVoidMethod CallStaticVoidMethod

CallIntMethod CallStaticVoidMethod

CallBooleanMethod CallStaticVoidMethod

CallByteMethod CallStaticVoidMethod

現(xiàn)在稍稍明白文章開(kāi)始構(gòu)造Java對(duì)象那個(gè)實(shí)例了吧?讓我們繼續(xù)深入一下:

Jni操作Java的String對(duì)象

從java程序中傳過(guò)去的String對(duì)象在本地方法中對(duì)應(yīng)的是jstring類(lèi)型,jstring類(lèi)型和c中的char*不同,所以如果你直接當(dāng)做char*使用的話,就會(huì)出錯(cuò)。因此在使用之前需要將jstring轉(zhuǎn)換成為c/c++中的char*,這里使用JNIEnv提供的方法轉(zhuǎn)換。

const char *str = (*env)->GetStringUTFChars(env, jstr, 0);

(*env)->ReleaseStringUTFChars(env, jstr, str);

這里使用GetStringUTFChars方法將傳進(jìn)來(lái)的prompt(jstring類(lèi)型)轉(zhuǎn)換成為UTF-8的格式,就能夠在本地方法中使用了。

注意:在使用完你所轉(zhuǎn)換之后的對(duì)象之后,需要顯示調(diào)用ReleaseStringUTFChars方法,讓JVM釋放轉(zhuǎn)換成UTF-8的string的對(duì)象的空間,如果不顯示的調(diào)用的話,JVM中會(huì)一直保存該對(duì)象,不會(huì)被垃圾回收器回收,因此就會(huì)導(dǎo)致內(nèi)存溢出。

下面是Jni訪問(wèn)String對(duì)象的一些方法:

GetStringUTFChars ? ? ? ? ?將jstring轉(zhuǎn)換成為UTF-8格式的char*

GetStringChars ? ? ? ? ? ? ? 將jstring轉(zhuǎn)換成為Unicode格式的char*

ReleaseStringUTFChars ? ?釋放指向UTF-8格式的char*的指針

ReleaseStringChars ? ? ? ? 釋放指向Unicode格式的char*的指針

NewStringUTF ? ? ? ? ? ? ? 創(chuàng)建一個(gè)UTF-8格式的String對(duì)象

NewString ? ? ? ? ? ? ? ? ? ?創(chuàng)建一個(gè)Unicode格式的String對(duì)象

GetStringUTFLength ? ? ?獲取UTF-8格式的char*的長(zhǎng)度

GetStringLength ? ? ? ? ? 獲取Unicode格式的char*的長(zhǎng)度

下面提供兩個(gè)String對(duì)象和char*互轉(zhuǎn)的方法:

/* 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;

}

總結(jié)

以上是生活随笔為你收集整理的android jni 调用java对象_Android NDK开发之Jni调用Java对象的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。