1. 程式人生 > >JNI/NDK開發指南(三)——JNI數據類型及與Java數據類型的映射關系

JNI/NDK開發指南(三)——JNI數據類型及與Java數據類型的映射關系

ons 轉換 類型 art return http 異常 array src


轉載請註明出處:http://blog.csdn.net/xyang81/article/details/42047899


當我們在調用一個Java native方法的時候。方法中的參數是怎樣傳遞給C/C++本地函數中的呢?Java方法中的參數與C/C++函數中的參數。它們之間是怎麽轉換的呢?我猜你應該也有相關的疑慮吧。咱們先來看一個樣例。還是以HelloWorld為例:

HelloWorld.java:

package com.study.jnilearn;

class MyClass {}

public class HelloWorld {
	
	public static native void test(short s, int i, long l, float f, double d, char c, 
			boolean z, byte b, String str, Object obj, MyClass p, int[] arr);

	public static void main(String[] args) {
		String obj = "obj";
		short s = 1;
		long l = 20;
		byte b = 127;
		test(s, 1, l, 1.0f, 10.5, 'A', true, b, "中國", obj, new MyClass(), new int[] {});
	}
	
	static {
		System.loadLibrary("HelloWorld");
	}
}

在HelloWorld.java中定義了一個test的native方法,該方法中一個共同擁有12個參數,當中前面8個為基本數據類型。後面4個所有為引用類型。



由HelloWorld.class生成的native函數原型及實現:

/*
 * Class:     com_study_jnilearn_HelloWorld
 * Method:    test
 * Signature: (SIJFDCZBLjava/lang/String;Ljava/lang/Object;Lcom/study/jnilearn/MyClass;[I)V
 */
JNIEXPORT void JNICALL Java_com_study_jnilearn_HelloWorld_test
    (JNIEnv *env, jclass cls, jshort s, jint i, jlong l, jfloat f,
     jdouble d, jchar c, jboolean z, jbyte b, jstring j_str, jobject jobj1, jobject job2, jintArray j_int_arr)
{
    printf("s=%hd, i=%d, l=%ld, f=%f, d=%lf, c=%c, z=%c, b=%d", s, i, l, f, d, c, z, b);
    const char *c_str = NULL;
    c_str = (*env)->GetStringUTFChars(env, j_str, NULL);
    if (c_str == NULL)
    {
        return; // memory out
    }
    (*env)->ReleaseStringUTFChars(env, j_str, c_str);
    printf("c_str: %s\n", (char*)c_str);
}

調用test方法的輸出結果:

技術分享

從頭文件函數的原型能夠得知,test方法中形參的數據類型自己主動轉換成了JNI中對應的數據類型,不難理解,在調用Java native方法將實參傳遞給C/C++函數的時候,會自己主動將java形參的數據類型自己主動轉換成C/C++對應的數據類型,所以我們在寫JNI程序的時候。必需要明確它們之間數據類型的對應關系。

在Java語言中數據類型分為基本數據類型和引用類型。其中基本數據類型有8種:byte、char、short、int、long、float、double、boolean。除了基本數據類型外其他都是引用類型:Object、String、數組等。8種基本數據類型分別相應JNI數據類型中的jbyte、jchar、jshort、jint、jlong、jfloat、jdouble、jboolean。

全部的JNI引用類型全部是jobject類型,為了使用方便和類型安全,JNI定義了一個引用類型集合。集合其中的全部類型都是jobject的子類,這些子類和Java中經常使用的引用類型相相應。比如:jstring表示字符串、jclass表示class字節碼對象、jthrowable表示異常、jarray表示數組,另外jarray派生了8個子類,分別相應Java中的8種基本數據類型(jintArray、jshortArray、jlongArray等)。以下再回想頭來看看test方法與Java_com_study_jnilearn_HelloWorld_test函數中參數類型的相應關系:

// HelloWorld.java
public static native void test(short s, int i, long l, float f, double d, char c, 
			boolean z, byte b, String str, Object obj, MyClass p);

// HelloWorld.h
JNIEXPORT void JNICALL Java_com_study_jnilearn_HelloWorld_test
  (JNIEnv *, jclass, jshort, jint, jlong, jfloat, jdouble, jchar, jboolean, jbyte, jstring, jobject, jobject, jintArray);

從上面兩個函數的參數中能夠看出來。除了JNIEnv和jclass這兩個參數外,其他參數都是一一相應的。以下是JNI規範文檔中描寫敘述Java與JNI數據類型的相應關系:

基本數據類型:

技術分享


引用類型:

技術分享

註意:

1、JNI假設使用C++語言編寫的話,全部引用類型派生自jobject,使用C++的繼承結構特性,使用對應的類型。

例如以下所看到的:

class _jobject {};
   class _jclass : public _jobject {};
   class _jstring : public _jobject {};
   class _jarray : public _jobject {};
   class _jbooleanArray : public _jarray {};
   class _jbyteArray : public _jarray {};
   ...

2、JNI假設使用C語言編寫的話。全部引用類型使用jobject,其他引用類型使用typedef又一次定義,如:typedef jobject jstring


jvalue類型:

jvalue是一個unio(聯合)類型。在C語中為了節約內存,會用聯合類型變量來存儲聲明在聯合體中的隨意類型數據 。在JNI中將基本數據類型與引用類型定義在一個聯合類型中,表示用jvalue定義的變量,能夠存儲隨意JNI類型的數據,後面會介紹jvalue在JNI編程其中的應用。原型例如以下:

typedef union jvalue {
    jboolean z;
    jbyte    b;
    jchar    c;
    jshort   s;
    jint     i;
    jlong    j;
    jfloat   f;
    jdouble  d;
    jobject  l;
} jvalue;
假設對unio類型不太明確的同學,請參考相關資料,在這裏不細講。



JNI/NDK開發指南(三)——JNI數據類型及與Java數據類型的映射關系