久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Java層調(diào)用native層的方法

 思想戰(zhàn)神 2020-05-07

前言

http://www./archives/1097中,,我介紹了下了如何編寫一個簡單的Demo來讓native輸出hello world到j(luò)ava層,,接下來本篇主要介紹Java層調(diào)用native方法,以及native層調(diào)用Java層的方法以及修改Java對象的屬性,。

Java層調(diào)用native層的方法

其實(shí)在上一篇中已經(jīng)介紹了下如何調(diào)用native層方法,,其實(shí)與調(diào)用普通的Java方法沒有什么區(qū)別,只是方法由native層實(shí)現(xiàn)的而已,。

首先我們在Java類中編寫native方法,,然后使用上一篇博客中介紹的方法在native層實(shí)現(xiàn)之。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package org.ndk.ndkfirst;
public class NDKTest {
    private static final String TAG = "NDKTest";
    static {
        System.loadLibrary("ndk-test-lib");
    }
    private String mString = "Ndk test string";
    /**
     * 在native中進(jìn)行加法運(yùn)算
     */
    public native int calcInNative(int num1, int num2);
}
1
2
3
4
5
6
7
8
9
#include <jni.h>
extern "C"
{
JNIEXPORT jint JNICALL
Java_org_ndk_ndkfirst_NDKTest_calcInNative(JNIEnv *env, jobject obj, jint num1, jint num2) {
return num1 + num2;
}
}

我們可以看到,,只是將加法運(yùn)算在native層實(shí)現(xiàn)而已,,調(diào)用native方法與普通Java方法一樣的,調(diào)用代碼如下,。

1
2
NDKTest nDKTest = new NDKTest();
nDKTest.calcInNative(1, 2);

native層調(diào)用Java方法

Java數(shù)據(jù)類型的對應(yīng)

在native層調(diào)用Java方法,,首先得知道Java類型與native的對應(yīng)關(guān)系,以及Java類型以及方法在native中的簽名格式,。

對于基礎(chǔ)類型,,對應(yīng)關(guān)系如下。這些數(shù)據(jù)類型的定義全在jni.h中

1
2
3
4
5
6
7
8
9
10
#define JNI_FALSE   0
#define JNI_TRUE    1
typedef unsigned char   jboolean;       /* unsigned 8 bits */
typedef signed char     jbyte;          /* signed 8 bits */
typedef unsigned short  jchar;          /* unsigned 16 bits */
typedef short           jshort;         /* signed 16 bits */
typedef int             jint;           /* signed 32 bits */
typedef long long       jlong;          /* signed 64 bits */
typedef float           jfloat;         /* 32-bit IEEE 754 */
typedef double          jdouble;        /* 64-bit IEEE 754 */

對于非基礎(chǔ)類型,,比如String等,Array等統(tǒng)一對應(yīng)jobject對象,。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class _jobject {};
class _jclass : public _jobject {};
class _jstring : public _jobject {};
class _jarray : public _jobject {};
class _jobjectArray : public _jarray {};
class _jbooleanArray : public _jarray {};
class _jbyteArray : public _jarray {};
class _jcharArray : public _jarray {};
class _jshortArray : public _jarray {};
class _jintArray : public _jarray {};
class _jlongArray : public _jarray {};
class _jfloatArray : public _jarray {};
class _jdoubleArray : public _jarray {};
class _jthrowable : public _jobject {};
typedef _jobject*       jobject;
typedef _jclass*        jclass;
typedef _jstring*       jstring;
typedef _jarray*        jarray;
typedef _jobjectArray*  jobjectArray;
typedef _jbooleanArray* jbooleanArray;
typedef _jbyteArray*    jbyteArray;
typedef _jcharArray*    jcharArray;
typedef _jshortArray*   jshortArray;
typedef _jintArray*     jintArray;
typedef _jlongArray*    jlongArray;
typedef _jfloatArray*   jfloatArray;
typedef _jdoubleArray*  jdoubleArray;
typedef _jthrowable*    jthrowable;
typedef _jobject*       jweak;

Java類型以及方法簽名

在native中調(diào)用Java層的方法以及屬性的時候需要使用相應(yīng)的簽名表示方法以及屬性,,下面就來介紹下基礎(chǔ)類型與引用類型的簽名表示方法。

從上面的表可以看到,,基礎(chǔ)類型是使用一個大寫字母表示,,對于數(shù)據(jù)則是使用[數(shù)組類型簽名,比如int[]數(shù)組的簽名為[I,,一維數(shù)組是一個[,,多維數(shù)組就是多個[[[,對于Java中的對象則是L類全路徑;,不要忘記結(jié)尾的;號,,對于對于函數(shù)方法則是(參數(shù)一簽名參數(shù)二簽名...)返回值簽名,,中間沒有空格。

比如上面的 public native int calcInNative(int num1, int num2);方法的前面為(II)I,其他的類似,。

native調(diào)用Java中的方法

首先我們得知道,,任何jni的方法都需要通過JNIEnv *env參數(shù)去調(diào)用

1
2
3
4
//C++形式
env->方法名
//C形式
(*env)->方法名

native層調(diào)用Java層方法以及屬性的時候類似于使用反射去調(diào)用Java的方法,基本分為如下幾步,。

1,、獲取jclass對象(類似于Java中的Class對象)

1
2
3
4
5
6
7
//方法一,,通過jobject對象直接獲取
jclass jclass1 = env->GetObjectClass(jobject);
//方法二,通過類描述符獲取
//匿名類使用$號隔開,,比如Build中定義的VERSION->android/os/Build$VERSION
env->FindClass(類描述符);
//這里不是Ljava/lang/String;的形式,,只有在參數(shù)列表中需要這么寫
jclass cls = env->FindClass("java/lang/String");

2、獲取jmethodID或者jfieldID(類似于Java中的Method或者Field)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//獲取非靜態(tài)方法
//參數(shù)const char *name 方法名
//參數(shù)const char *sig 方法簽名
jmethodID env->GetMethodID(jclass clazz, const char *name, const char *sig)
//獲取靜態(tài)方法
jmethodID env->GetStaticMethodID(jclass clazz, const char *name, const char *sig)
//獲取非靜態(tài)的成員變量
jfieldID env->GetFieldID(jclass clazz, const char *name, const char *sig)
//獲取靜態(tài)的成員變量
jfieldID env->GetStaticFieldID(jclass clazz, const char *name, const char *sig)
//獲取指定類型的成員變量,,如下面一個
jboolean env->Get[Type]Field(jobject obj, jfieldID fieldID)
jboolean env->GetBooleanField(jobject obj, jfieldID fieldID)
//獲取指定類型的靜態(tài)成員變量,,如下面一個
jboolean env->GetStatic[Type]Field(jclass clazz, jfieldID fieldID)
jboolean env->GetStaticBooleanField(jclass clazz, jfieldID fieldID)

3、調(diào)用相應(yīng)函數(shù)以及獲取/修改屬性值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//調(diào)用Java方法
env->Call[Type]Method(...)
jobject env->CallBooleanMethod(jobject obj, jmethodID methodID, ...)
// 調(diào)用Java靜態(tài)方法
env->CallStatic[Type]Method(...)
jboolean env->CallStaticBooleanMethod(jclass clazz, jmethodID methodID, ...)
//獲取Java屬性值
env->Get[Type]Field()
jint env->GetIntField(jobject obj, jfieldID fieldID)
//獲取Java靜態(tài)屬性值
env->GetStatic[Type]Field()
jboolean env->GetStaticBooleanField(jclass clazz, jfieldID fieldID)
//設(shè)置Java屬性值
env->Set[Type]Field()
void env->SetBooleanField(jobject obj, jfieldID fieldID, jboolean value)
//設(shè)置Java靜態(tài)屬性值
env->SetStatic[Type]Field()
void env->SetStaticBooleanField(jclass clazz, jfieldID fieldID, jboolean value)

native調(diào)用舉例

由于本篇博客篇幅已經(jīng)較長,,所以這里只給出部分關(guān)鍵代碼,。下面為Java層代碼。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package org.ndk.ndkfirst;
import android.util.Log;
public class NDKTest {
    private static final String TAG = "NDKTest";
    static {
        System.loadLibrary("ndk-test-lib");
    }
    private String mString = "Ndk test string";
    /**
     * 在native中調(diào)用java方法
     */
    public native void callJavaMetood();
    /**
     * 在native中修改對象的字段
     */
    public native void modifyFiled();
/**
* 輸出成員變量的值
*/
    public void outputString() {
        Log.i(TAG, "mString: " + mString);
    }
/**
* 在native中調(diào)用此方法
*/
    @Override
    public String toString() {
        Log.i(TAG, "toString: ");
        return mString;
    }
}

對應(yīng)的native層實(shí)現(xiàn),。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <jni.h>
extern "C"
{
JNIEXPORT void JNICALL Java_org_ndk_ndkfirst_NDKTest_callJavaMetood(JNIEnv *env, jobject obj) {
jclass jclass1 = env->GetObjectClass(obj);
jmethodID methodID = env->GetMethodID(jclass1, "toString", "()Ljava/lang/String;");
env->CallObjectMethod(obj, methodID);
}
JNIEXPORT void JNICALL Java_org_ndk_ndkfirst_NDKTest_modifyFiled(JNIEnv *env, jobject obj) {
jclass jclass1 = env->GetObjectClass(obj);
jfieldID fieldID1 = env->GetFieldID(jclass1,"mString","Ljava/lang/String;");
env->SetObjectField(obj,fieldID1,env->NewStringUTF("native modify it"));
}
}

Demo地址:github

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多