JNI java和c之間對象的傳遞

在寫JNI時java與C之間的數據傳遞是很尋常的,這裏分析下集中java和C之間的傳值情況。


1.java與C之間的基本數據傳遞。

在這之前有必要先了解java與C之間基本類型映射關係,如下表所示:

Java 類型 本地類型 描述
boolean jboolean C/C++8位整型
byte jbyte C/C++帶符號的8位整型
char jchar C/C++無符號的16位整型
short jshort C/C++帶符號的16位整型
int jint C/C++帶符號的32位整型
long jlong C/C++帶符號的64位整型e
float jfloat C/C++32位浮點型
double jdouble C/C++64位浮點型
Object jobject 任何Java對象,或者沒有對應java類型的對象
Class jclass Class對象
String jstring 字符串對象
Object[] jobjectArray 任何對象的數組
boolean[] jbooleanArray 布爾型數組
byte[] jbyteArray 比特型數組
char[] jcharArray 字符型數組
short[] jshortArray 短整型數組
int[] jintArray 整型數組
long[] jlongArray 長整型數組
float[] jfloatArray 浮點型數組
double[] jdoubleArray 雙浮點型數組
java和C之間的數據進行傳遞過程中都是需要進行轉換的,轉換關係就是上表。

舉個從C返回字符串給Java的例子,C代碼如下(這裏是C++實現):

JNIEXPORT jstring JNICALL Java_perfecter_jni_LoadJni_printFromC(JNIEnv* env,
		jobject obj) {
	jstring str = env->NewStringUTF("Hello from JNI !");
	return str;
}
對應的java本地方法聲明如下:
public static native String printFromC();

這裏就拿java的String與C的jstring舉例了,上面 JNIEXPORT 和 JNICALL 是關鍵字。


2.java向C傳遞對象,C調用java對象的方法。

直接用代碼說明,

JNIEXPORT jstring JNICALL Java_perfecter_jni_LoadJni_getStringFromJavaObj(
		JNIEnv* env, jobject obj, jobject clsObj){
	jmethodID methodId;

	jclass objclass=env->GetObjectClass(clsObj);

	methodId=env->GetMethodID(objclass,"getString","()Ljava/lang/String;");

	jstring jstr=(jstring)env->CallObjectMethod(clsObj,methodId,NULL);

	return jstr;
}
java native方法 
public static native String getStringFromJavaObj(MyObj obj);


MyObj類:

package perfecter.jni;
public class MyObj
{
    private String name;
    
    public MyObj(){}
    
    public String getString(){
        return "String from MyObj"+name;
    }
}

應該很快可以看出來,C中代碼就是java中的反射機制。這裏說明下,像GetObjectClass這些函數可以到sun的jni官方文檔去查詢。

說明下GetMethodID(objclass,"getString","()Ljava/lang/String;"),參數依次爲方法對象的jclass對象,方法名稱,方法簽名。

方法簽名由方法參數和方法返回值構成,這裏又分爲基本數據類型和引用類型,

基本數據類型對應關係表如下:

引用類型規則如下:

以“L”開頭,以“;”結束,中間對應的是該類型的路徑

       如:String : Ljava/lang/String;

              Object: Ljava/lang/Object;

       自定義類 MyObj 對應  package perfecter.jni.MyObj;

              MyObj : Lperfecter/jni/MyObj;

"."換成“/”。

數組表示:  數組表示的時候以“[” 爲標誌,一個“[”表示一個維度

       如:int [ ] :[I

              Long[ ][ ]  : [[J

              Object[ ][ ][ ] : [[[Ljava/lang/Object;

其實不知道怎麼生成簽名的可以直接用命令行去查看,具體做法是在生成的類的class目錄下執行 javap –s MyObj.

3.C向java傳遞對象

直接看代碼,

JNIEXPORT jobject JNICALL Java_perfecter_jni_LoadJni_getJavaObj(JNIEnv* env,
		jobject obj){
	jclass clazz=env->FindClass("perfecter/jni/MyObj");

	if(clazz==0)
		return 0;

	jobject jobj=env->AllocObject(clazz);

	jfieldID fieldId=env->GetFieldID(clazz,"name","Ljava/lang/String;");

	env->SetObjectField(jobj,fieldId,env->NewStringUTF("wahaha"));

	return jobj;
}
java對應的native方法申明public static native MyObj getJavaObj();

這個就是在C中構建對象,設置好屬性後傳過去。



最後附上JNI文檔地址:http://java.sun.com/docs/books/jni/html/jniTOC.html



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章