深入理解Android(4)——理解Android中的JNI(下)

來源:互聯網
上載者:User

標籤:android   ndk   jni   

在前面文章中簡單介紹了JNI,這一篇文章來簡單看一下jni.h中定義的一些常用方法,來實現通過C++調用Android中的Java代碼。

轉載請說明出處:http://blog.csdn.net/dawanganban

一、兩個參數的介紹

在前面的代碼中我們會遇到兩個參數,下面對這兩個參數做一解釋

1、JNIEnv是指向可用JNI函數表的介面指標,C代碼中JNIEnv是指向JNINativeInterface結構的指標,在C語言中JNIEnv必須作為第一個參數傳入每一個JNI函數的調用者,如:

(*env)->NewStringUTF(env, "helloworld");
在C++中,JNIEnv是C++類的執行個體,JNI函數以成員函數形式存在,所以在JNI環境中,無序傳入該參數,如:

env->NetStringUTF("helloworld");
2、jobject是一個指向java對象的引用,如果本地方法是一個靜態方法,則是指向類位元組碼檔案的class對象。

二、JNI資料類型

1、基本類型映射

從上表中可以看出,Java的資料類型和C++的基礎資料型別 (Elementary Data Type)有一個映射關係,我們在使用JNI的時候可以直接使用Natvie Type來操作Native層的資料,這樣就不用記憶複雜的映射關係了,從變數的名字上我們可以看到在Java的基礎資料型別 (Elementary Data Type)前面加一個字母‘j‘就是對應的C++的Native類型。

2、參考型別映射


與基本類型不同的是,參考型別對原生的方法是不透明的(不能直接使用和修改),JNI提供了與這些參考型別密切相關的一組API,這些API通過JNIEnv介面指標提供給原生函數。

我們在jni.h中可以看到上面類型的定義:

class _jobject {};class _jclass : public _jobject {};class _jthrowable : public _jobject {};class _jstring : public _jobject {};class _jarray : public _jobject {};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 _jobjectArray : public _jarray {};typedef _jobject *jobject;typedef _jclass *jclass;typedef _jthrowable *jthrowable;typedef _jstring *jstring;typedef _jarray *jarray;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 _jobjectArray *jobjectArray;
這些類的設計和Java一樣,都繼承自一個名為_jobject的父類。

三、對參考型別操作的例子

package com.example.test;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Toast;import com.example.myfirstjniproj.R;/** * 陽光小強 http://blog.csdn.net/dawanganban * @author lixiaoqiang * */public class MainActivity extends Activity implements OnClickListener{@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);findViewById(R.id.jni_jstring_button).setOnClickListener(this);findViewById(R.id.jni_javaArray_button).setOnClickListener(this);}@Overridepublic void onClick(View view) {switch (view.getId()) {case R.id.jni_jstring_button:showToast(jniStringTest("input string"));break;case R.id.jni_javaArray_button:int[] array = jniArrayTest();showToast("arr[1]=" + array[1] + " : arr[2]=" + array[2]);break;default:break;}}private void showToast(String content){Toast.makeText(MainActivity.this, content, Toast.LENGTH_SHORT).show();}public native String jniStringTest(String str);public native int[] jniArrayTest();static{System.loadLibrary("jnitest");}}
通過javah產生的標頭檔

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_example_test_MainActivity */#ifndef _Included_com_example_test_MainActivity#define _Included_com_example_test_MainActivity#ifdef __cplusplusextern "C" {#endif/* * Class:     com_example_test_MainActivity * Method:    jniStringTest * Signature: (Ljava/lang/String;)Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_example_test_MainActivity_jniStringTest  (JNIEnv *, jobject, jstring);/* * Class:     com_example_test_MainActivity * Method:    jniArrayTest * Signature: ()[I */JNIEXPORT jintArray JNICALL Java_com_example_test_MainActivity_jniArrayTest  (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif
c++實現

#include "com_example_test_MainActivity.h"#include <stdlib.h>using namespace std;JNIEXPORT jstring JNICALL Java_com_example_test_MainActivity_jniStringTest  (JNIEnv * env, jobject obj, jstring str){//將java字串轉成c++字串jboolean isCopy;const char* cstr = env->GetStringUTFChars(str, &isCopy);//釋放原生字串env->ReleaseStringUTFChars(str, cstr);//建立字串jstring jstr = env->NewStringUTF("hello world");;return jstr;}JNIEXPORT jintArray JNICALL Java_com_example_test_MainActivity_jniArrayTest  (JNIEnv * env, jobject obj){//建立一個10個元素的數組jintArray intarray = env->NewIntArray(10);if(0 != intarray){jint nativeArray[10];//擷取原生的數組env->GetIntArrayRegion(intarray, 0, 10, nativeArray);nativeArray[1] = 10;nativeArray[2] = 20;//設定改變env->SetIntArrayRegion(intarray, 0, 10, nativeArray);}return intarray;}
四、訪問域和擷取ID

Java有兩個域:執行個體域和靜態域,每個執行個體都有自己的執行個體域副本,而一個類的所有執行個體共用一個靜態域。

JNIEXPORT jstring JNICALL Java_com_example_test_MainActivity_getInstanceField  (JNIEnv * env, jobject obj){//通過對象獲得類jclass clazz;clazz = env->GetObjectClass(obj);//獲得執行個體域IdjfieldID instanceFieldId;instanceFieldId = env->GetFieldID(clazz, "instanceField", "Ljava/lang/String");//獲得執行個體域jobject instanceField;instanceField = env->GetObjectField(obj, instanceFieldId);jstring jstr = env->NewStringUTF("擷取成功");return jstr;}JNIEXPORT jstring JNICALL Java_com_example_test_MainActivity_getStaticField  (JNIEnv * env, jobject obj){jclass clazz;clazz = env->GetObjectClass(obj);jfieldID staticFieldId;staticFieldId = env->GetStaticFieldID(clazz, "staticField", "Ljava/lang/String");jobject staticField;staticField = env->GetStaticObjectField(clazz, staticFieldId);jstring jstr = env->NewStringUTF("擷取成功");return jstr;}
在上面代碼中我們看到了“Ljava/lang/String"字串,這個是擷取ID的類型簽名,Java的類型簽名映射表如下:


五、調用Java中的方法

與上面的域一樣,Java中也有兩類方法,執行個體方法和靜態方法,JNI提供了兩類方法的函數

public native void getInstanceMethod();public native void getStaticMethod();public String instanceMethod(){return "instanceMethod";}public static String staticMethod(){return "staticMethod";}
JNIEXPORT void JNICALL Java_com_example_test_MainActivity_getInstanceMethod  (JNIEnv * env, jobject obj){jclass clazz;clazz = env->GetObjectClass(obj);jmethodID instanceMethodId;instanceMethodId = env->GetMethodID(clazz, "instanceMethod", "()Ljava/lang/String");jstring instanceMethodResult;instanceMethodResult = env->CallStringMethod(obj, instanceMethodId);}JNIEXPORT void JNICALL Java_com_example_test_MainActivity_getStaticMethod  (JNIEnv * env, jobject obj){jclass clazz;clazz = env->GetObjectClass(obj);jmethodID staticMethodId;staticMethodId = env->GetStaticMethodID(clazz, "staticMethod", "()Ljava/lang/String");jstring staticMethodResult;staticMethodResult = env->CallStaticStringMethod(clazz, staticMethodId);}

深入理解Android(4)——理解Android中的JNI(下)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.