转 java c++互传arraylist
Java JNI由淺入深(包括:Java和C++互傳ArrayList泛型對象參數(shù))
2010-11-25 09:57?1694人閱讀?評論(1)?收藏?舉報?
?? ? ? ? 我們知道Java是一個運(yùn)行在虛擬機(jī)里面的高級的編程語言,如果要調(diào)用系統(tǒng)的動態(tài)鏈接庫的話,就要先聲明native修飾的方法(類似接口里面的方法),再由C/C++程序來實現(xiàn)(類似實現(xiàn)接口里的方法)。這樣Java調(diào)用這些native方法就相當(dāng)于調(diào)用了C/C++里面實現(xiàn)了的方法。通常我們把這種機(jī)制叫做JNI(Java NativeInterfac),即Java?本地編程接口
? ?? ?? ? Android也同理,要學(xué)會在Android上進(jìn)行NDK開發(fā),首先我們到打好java JNI的基礎(chǔ)。現(xiàn)在我們暫時把Android開發(fā)丟到一邊先,試試在Java之下編譯一個C動態(tài)鏈接庫,再用Java程序調(diào)用。
?
1)先來個最簡單的打印HelloWorld例子:
Java代碼(HelloJni.java):
?
[java]?view plaincopy- import?java.util.*;??
- public?class?HelloJni{??
- ??????
- ????static{??
- ????????System.loadLibrary("hello");??
- ????}??
- ????public?native?static?void?sayHello();??
- ????public?static?void?main(String?[]?args)??
- ????{??
- ????????????????HelloJni.sayHello();??
- ????}??
- }??
?
生成頭文件(HelloJni.h):
先javac HelloJni.java編譯你的Java源碼,再javah–jni HelloJni生成所需的頭文件
頭文件內(nèi)容是這樣的:
?
[java]?view plaincopy- /*?DO?NOT?EDIT?THIS?FILE?-?it?is?machine?generated?*/??
- #include?<jni.h>??
- /*?Header?for?class?HelloJni?*/??
- #ifndef?_Included_HelloJni??
- #define?_Included_HelloJni??
- #ifdef?__cplusplus??
- extern?"C"?{??
- #endif??
- JNIEXPORT?void?JNICALL?Java_HelloJni_sayHello?(JNIEnv?*,?jclass);??
- #ifdef?__cplusplus??
- }??
- #endif??
- #endif??
?
實現(xiàn)頭文件聲明的方法(HelloJni.cpp)
?
[c-sharp]?view plaincopy- #include?"HelloJni.h"??
- JNIEXPORT?void?JNICALL?Java_HelloJni_sayHello(JNIEnv?*env,?jclass?cls)??
- {??
- ???????printf("HelloWorld");??
- }??
?
?
編譯命令:?g++ -I$JAVA_HOME/include-I$JAVA_HOME/include/linux HelloJni.cpp -shared -o libhello.so
命令參數(shù)解析:-I?是指引入java虛擬機(jī)的庫的路徑,-shared?是指編譯成動態(tài)鏈接庫(共享庫) –o?輸出文件名(注意,在Linux平臺下的動態(tài)鏈接庫有一個命名格式:“l(fā)ib+庫名+.so”在java代碼里面loadLibrary的時候不要加lib前綴和.so后綴)
由于我這里把這個動態(tài)鏈接庫編譯放在當(dāng)前目錄下,所以還要設(shè)置環(huán)境變量LD_LIBRARY_PATH=該so動態(tài)鏈接庫所在的目錄,才能正常運(yùn)行
?
?
#############################+++華麗的分割線+++###########################
?
2)好了,可以打印HelloWorld出來后,我們再深入一點(diǎn)點(diǎn),傳入一個int的數(shù),在C/C++代碼里面加1后返回。
?
Java代碼(HelloJni.java):
?
[java]?view plaincopy- public?class?HelloJni{??
- ????????static{??
- ???????????????????System.loadLibrary("hello");??
- ????????}??
- ????????public?static?native?void?sayHello();??
- ????????public?native?int?getInt();??
- ????????public?native?void?setInt(int?i);??
- ????????public?static?void?main(String?args[]){??
- ????????//??????HelloJni.sayHello();??
- ?????????????????HelloJni?hello?=?new?HelloJni();??
- ?????????????????hello.setInt(2);??
- ?????????????????System.out.println(hello.getInt());??
- ????????}??
- }??
?
生成頭文件(HelloJni.h):
?
[c-sharp]?view plaincopy- /*?DO?NOT?EDIT?THIS?FILE?-?it?is?machine?generated?*/??
- #include?<jni.h>??
- /*?Header?for?class?HelloJni?*/??
- #ifndef?_Included_HelloJni??
- #define?_Included_HelloJni??
- #ifdef?__cplusplus??
- extern?"C"?{??
- #endif??
- JNIEXPORT?void?JNICALL?Java_HelloJni_sayHello?(JNIEnv?*,?jclass);??
- JNIEXPORT?jint?JNICALL?Java_HelloJni_getInt?(JNIEnv?*,?jobject);??
- JNIEXPORT?void?JNICALL?Java_HelloJni_setInt?(JNIEnv?*,?jobject,?jint);??
- #ifdef?__cplusplus??
- }??
- #endif??
- #endif??
?
實現(xiàn)頭文件聲明的方法(HelloJni.cpp)
?
[java]?view plaincopy- #include?"HelloJni.h"??
- int?i=1;??
- JNIEXPORT?void?JNICALL?Java_HelloJni_sayHello??
- ??(JNIEnv?*env,?jclass?cls){??
- ????????printf("HelloWorld/n");??
- }??
- JNIEXPORT?jint?JNICALL?Java_HelloJni_getInt??
- ??(JNIEnv?*env,?jobject?thiz){??
- ????????return?i;??
- }??
- JNIEXPORT?void?JNICALL?Java_HelloJni_setInt??
- ??(JNIEnv?*env,?jobject?thiz,jint?ji){??
- ????????i?=?ji+1;??
- }??
?
運(yùn)行結(jié)果:打印2
3)只是傳入簡單的數(shù)據(jù)類型不爽,這次讓C/C++生成個Java對象返回
?
Java代碼:pojo實體類(User.java)
?
[c-sharp]?view plaincopy- public?class?User{??
- ????????private?long?id;??
- ????????private?String?userName;??
- ????????private?boolean?isMan;??
- ????????private?int?age;??
- ????????public?User(){}??
- ????????public?User(long?id,?String?userName,?boolean?isMan,?int?age)?{??
- ????????????????super();??
- ????????????????this.id?=?id;??
- ????????????????this.userName?=?userName;??
- ????????????????this.isMan?=?isMan;??
- ????????????????this.age?=?age;??
- ????????}??
- ????????public?long?getId()?{??
- ????????????????return?id;??
- ????????}??
- ????????public?void?setId(long?id)?{??
- ????????????????this.id?=?id;??
- ????????}??
- ????????public?String?getUserName()?{??
- ????????????????return?userName;??
- ????????}??
- ????????public?void?setUserName(String?userName)?{??
- ????????????????this.userName?=?userName;??
- ????????}??
- ????????public?boolean?isMan()?{??
- ????????????????return?isMan;??
- ????????}??
- ????????public?void?setMan(boolean?isMan)?{??
- ????????????????this.isMan?=?isMan;??
- ????????}??
- ????????public?int?getAge()?{??
- ????????????????return?age;??
- ????????}??
- ????????public?void?setAge(int?age)?{??
- ????????????????this.age?=?age;??
- ????????}??
- }??
?
Java代碼(HelloJni.java):
?
[java]?view plaincopy- public?class?HelloJni{??
- ????????static{??
- ????????????????System.loadLibrary("userbean");??
- ????????}??
- ????????public?static?native?void?sayHello();??
- ????????public?native?int?getInt();??
- ????????public?native?void?setInt(int?i);??
- ????????public?native?void?setUser(String?userName);??
- ????????public?native?User?getUser();??
- ????????public?static?void?main(String?args[]){??
- ????????//??????HelloJni.sayHello();??
- ????????????????HelloJni?hello?=?new?HelloJni();??
- ????????//??????hello.setInt(2);??
- ????????//??????System.out.println(hello.getInt());??
- ????????????????hello.setUser("LiangYaotian");??
- ????????????????User?user?=?hello.getUser();??
- ????????????????System.out.println("user?from?c/c++");??
- ????????????????System.out.println("name:"+user.getUserName());??
- ????????????????System.out.println("isMan?:"+user.isMan());??
- ????????????????System.out.println("age:"+user.getAge());??
- ????????}??
- }??
?
生成頭文件(HelloJni.h):
?
[c-sharp]?view plaincopy- #include?<jni.h>??
- /*?Header?for?class?HelloJni?*/??
- #ifndef?_Included_HelloJni??
- #define?_Included_HelloJni??
- #ifdef?__cplusplus??
- extern?"C"?{??
- #endif??
- JNIEXPORT?void?JNICALL?Java_HelloJni_sayHello?(JNIEnv?*,?jclass);??
- JNIEXPORT?jint?JNICALL?Java_HelloJni_getInt?(JNIEnv?*,?jobject);??
- JNIEXPORT?void?JNICALL?Java_HelloJni_setInt?(JNIEnv?*,?jobject,?jint);??
- JNIEXPORT?void?JNICALL?Java_HelloJni_setUser?(JNIEnv?*,?jobject,?jstring);??
- JNIEXPORT?jobject?JNICALL?Java_HelloJni_getUser??(JNIEnv?*,?jobject);??
- #ifdef?__cplusplus??
- }??
- #endif??
- #endif??
?
實現(xiàn)頭文件聲明的方法(HelloJni.cpp)
?
[c-sharp]?view plaincopy- #include?<iostream>??
- #include?<stdio.h>??
- using?namespace?std;??
- int?i=1;??
- jobject?user;??
- JNIEXPORT?void?JNICALL?Java_HelloJni_sayHello??
- ??(JNIEnv?*env,?jclass?cls){??
- ????????printf("HelloWorld/n");??
- }??
- JNIEXPORT?jint?JNICALL?Java_HelloJni_getInt??
- ??(JNIEnv?*env,?jobject?thiz){??
- ????????return?i;??
- }??
- JNIEXPORT?void?JNICALL?Java_HelloJni_setInt??
- ??(JNIEnv?*env,?jobject?thiz,jint?ji){??
- ????????i?=?ji+1;??
- }??
- JNIEXPORT?void?JNICALL?Java_HelloJni_setUser??
- ??(JNIEnv?*env,?jobject?thiz,?jstring?name){??
- ????????jclass?userClass?=?env->FindClass("User");??
- ????????jmethodID?userMethod?=?env->GetMethodID(userClass,"<init>","()V");??
- ????????jfieldID?mId?=?env->GetFieldID(userClass,"id","J");??
- ????????jfieldID?mUserName?=?env->GetFieldID(userClass,"userName","Ljava/lang/String;");??
- ????????jfieldID?mIsMan?=?env->GetFieldID(userClass,"isMan","Z");??
- ????????jfieldID?mAge?=?env->GetFieldID(userClass,"age","I");??
- ????????jobject?userObject?=?env->NewObject(userClass,userMethod);??
- ????????env->SetObjectField(userObject,mUserName,name);??
- ????????env->SetLongField(userObject,mId,1001);??
- ????????env->SetBooleanField(userObject,mIsMan,1);??
- ????????env->SetIntField(userObject,mAge,21);??
- ????????user?=?userObject;??
- }??
?
?
?
4)有些同學(xué)可能會說:“返回個Java對象算什么啊,C/C++和Java之間互傳復(fù)雜對象才好玩呢!”正所謂“不怕做不到,就怕想不到”,我們接著重構(gòu)一下上面那個例子!
這次我們傳包含有User對象的List到C/C++程序里面
Java代碼(User.java)
同上。
Java代碼(HelloJni.java)
?
[java]?view plaincopy- import?java.util.*;??
- public?class?HelloJni{??
- ????????static{??
- ????????????????System.loadLibrary("userbean");??
- ????????}??
- ????????public?native?int?get();??
- ????????public?native?void?set(int?i);??
- ????????public?native?void?setUser(String?userName);??
- ????????public?native?User?getUser();??
- ????????public?native?void?setUserList(ArrayList<User>?userList);??
- ????????public?native?ArrayList<User>?getUserList();??
- ????????public?static?void?main(String?[]?args)??
- ????????{??
- ????????????????HelloJni?hello?=?new?HelloJni();??
- ????????//??????hello.set(2);??
- ????????//??????System.out.println(hello.get());??
- ????????/*?
- ????????????????hello.setUser("LiangYaotian");?
- ????????????????User?user?=?hello.getUser();?
- ????????????????System.out.println("user?from?c/c++");?
- ????????????????System.out.println("name:"+user.getUserName());?
- ????????????????System.out.println("isMan?:"+user.isMan());?
- ????????????????System.out.println("age:"+user.getAge());?
- ????????*/??
- ????????????????ArrayList<User>?userList?=?new?ArrayList<User>();??
- ????????????????for(int?i=0;i<10;i++){??
- ????????????????????????User?u?=?new?User((long)(1000+i),"LiangYaotian"+i,true,21);??
- ????????????????????????userList.add(u);??
- ????????????????}??
- ????????????????hello.setUserList(userList);??
- ????????????????userList?=?null;??
- ????????????????userList?=?hello.getUserList();??
- ????????????????System.out.println("ArrayList<User>?construct?from?C++,then?Java?print?it.....");??
- ????????????????for(User?u?:?userList){??
- ????????????????????????System.out.println("id:"+u.getId()+";?name:"+u.getUserName());??
- ????????????????}??
- ????????}??
- }??
?
C頭文件(HelloJni.h)
?
[java]?view plaincopy- #include?<jni.h>??
- /*?Header?for?class?HelloJni?*/??
- #ifndef?_Included_HelloJni??
- #define?_Included_HelloJni??
- #ifdef?__cplusplus??
- extern?"C"?{??
- #endif??
- JNIEXPORT?void?JNICALL?Java_HelloJni_sayHello?(JNIEnv?*,?jclass);??
- JNIEXPORT?jint?JNICALL?Java_HelloJni_getInt?(JNIEnv?*,?jobject);??
- JNIEXPORT?void?JNICALL?Java_HelloJni_setInt?(JNIEnv?*,?jobject,?jint);??
- JNIEXPORT?void?JNICALL?Java_HelloJni_setUser?(JNIEnv?*,?jobject,?jstring);??
- JNIEXPORT?jobject?JNICALL?Java_HelloJni_getUser??(JNIEnv?*,?jobject);??
?
頭文件的實現(xiàn)(HelloJni.cpp)
?
[java]?view plaincopy- #include?"HelloJni.h"??
- int?i=1;??
- jobject?user;??
- JNIEXPORT?jint?JNICALL?Java_HelloJni_get??
- ??(JNIEnv?*env,?jobject?jthiz){??
- ????????printf("HelloWorld/n");??
- }??
- JNIEXPORT?void?JNICALL?Java_HelloJni_set??
- ??(JNIEnv?*env,?jobject?jthiz,?jint?ji){??
- ????????i?=?ji+1;??
- }??
- JNIEXPORT?void?JNICALL?Java_HelloJni_setUser??
- ??(JNIEnv?*env,?jobject?jthiz,?jstring?name){??
- ????????jclass?userClass?=?env->FindClass("User");??
- ????????jmethodID?userMethod?=?env->GetMethodID(userClass,"<init>","()V");??
- ????????jfieldID?mId?=?env->GetFieldID(userClass,"id","J");??
- ????????jfieldID?mUserName?=?env->GetFieldID(userClass,"userName","Ljava/lang/String;");??
- ????????jfieldID?mIsMan?=?env->GetFieldID(userClass,"isMan","Z");??
- ????????jfieldID?mAge?=?env->GetFieldID(userClass,"age","I");??
- ????????jobject?userObject?=?env->NewObject(userClass,userMethod);??
- ????????env->SetObjectField(userObject,mUserName,name);??
- ????????env->SetLongField(userObject,mId,1001);??
- ????????env->SetBooleanField(userObject,mIsMan,1);??
- ????????env->SetIntField(userObject,mAge,21);??
- ????????user?=?userObject;??
- }??
- JNIEXPORT?jobject?JNICALL?Java_HelloJni_getUser??
- ??(JNIEnv?*env,?jobject?jthiz){??
- ????????return?user;??
- }??
- JNIEXPORT?void?JNICALL?Java_HelloJni_setUserList??
- ??(JNIEnv?*env,?jobject?jthiz,?jobject?userList){??
- ????????int?i;??
- ????????//class?ArrayList??
- ????????jclass?cls_arraylist?=?env->GetObjectClass(userList);??
- ????????//method?in?class?ArrayList??
- ????????jmethodID?arraylist_get?=?env->GetMethodID(cls_arraylist,"get","(I)Ljava/lang/Object;");??
- ????????jmethodID?arraylist_size?=?env->GetMethodID(cls_arraylist,"size","()I");??
- ????????jint?len?=?env->CallIntMethod(userList,arraylist_size);??
- ????????printf("get?java?ArrayList<User>?object?by?C++?,?then?print?it...../n");??
- ????????for(i=0;i<len;i++){??
- ????????????????jobject?obj_user?=?env->CallObjectMethod(userList,arraylist_get,i);??
- ????????????????jclass?cls_user?=?env->GetObjectClass(obj_user);??
- ????????????????jmethodID?user_getId?=?env->GetMethodID(cls_user,"getId","()J");??
- ????????????????jmethodID?user_getUserName?=?env->GetMethodID(cls_user,"getUserName","()Ljava/lang/String;");??
- ????????????????jmethodID?user_isMan?=?env->GetMethodID(cls_user,"isMan","()Z");??
- ????????????????jmethodID?user_getAge?=?env->GetMethodID(cls_user,"getAge","()I");??
- ????????????????jstring?name?=?(jstring)env->CallObjectMethod(obj_user,user_getUserName);??
- ????????????????jboolean?b?=?true;??
- ????????????????const?char?*namePtr?=?env->GetStringUTFChars(name,&b);??
- ????????????????jlong?id?=?env->CallLongMethod(obj_user,user_getId);??
- ????????????????jboolean?sex?=?env->CallBooleanMethod(obj_user,user_isMan);??
- ????????????????jint?age?=?env->CallIntMethod(obj_user,user_getAge);??
- ????????????????printf("Id:%d;?",id);??
- ????????????????printf("Name:%s;?",namePtr);??
- ????????????????printf("isMan??%d;?",sex);??
- ????????????????printf("Age:%d?/n?",age);??
- ????????}??
- }??
- JNIEXPORT?jobject?JNICALL?Java_HelloJni_getUserList??
- ??(JNIEnv?*env,?jobject?jthiz){??
- ????????//ArrayList?Object??
- ????????jclass?cls_ArrayList?=?env->FindClass("java/util/ArrayList");??
- ????????jmethodID?construct?=?env->GetMethodID(cls_ArrayList,"<init>","()V");??
- ????????jobject?obj_ArrayList?=?env->NewObject(cls_ArrayList,construct,"");??
- ????????jmethodID?arrayList_add?=?env->GetMethodID(cls_ArrayList,"add","(Ljava/lang/Object;)Z");??
- ????????//User?Object??
- ????????jclass?cls_user?=?env->FindClass("User");??
- ????????//none?argument?construct?function??
- ????????jmethodID?construct_user?=?env->GetMethodID(cls_user,"<init>","()V");??
- ????????//new?a?object??
- ????????jobject?obj_user?=?env->NewObject(cls_user,construct_user,"");??
- ????????//get?method?id??
- ????????/*?
- ????????jmethodID?user_setId?=?env->GetMethodID(cls_user,"setId","(J)V");?
- ????????jmethodID?user_setUserName?=?env->GetMethodID(cls_user,"setUserName","(Ljava/lang/String;)V");?
- ????????jmethodID?user_setMan?=?env->GetMethodID(cls_user,"setMan","(Z)V");?
- ????????jmethodID?user_setAge?=?env->GetMethodID(cls_user,"setAge","(I)V");?
- ????????*/??
- ????????int?i;??
- ????????for(i=0;i<10;i++){??
- ????????//new?a?object??
- ????????jobject?obj_user?=?env->NewObject(cls_user,construct_user,"");??
- ????????//get?field?id??
- ????????jfieldID?user_id?=?env->GetFieldID(cls_user,"id","J");??
- ????????jfieldID?user_name?=?env->GetFieldID(cls_user,"userName","Ljava/lang/String;");??
- ????????jfieldID?user_isMan?=?env->GetFieldID(cls_user,"isMan","Z");??
- ????????jfieldID?user_age?=?env->GetFieldID(cls_user,"age","I");??
- ????????env->SetLongField(obj_user,user_id,i);??
- ????????env->SetObjectField(obj_user,user_name,env->NewStringUTF("LiangYaoTian"));??
- ????????env->SetBooleanField(obj_user,user_isMan,1);??
- ????????env->SetIntField(obj_user,user_age,21);??
- ????????????????env->CallObjectMethod(obj_ArrayList,arrayList_add,obj_user);??
- ????????}??
- ????????return?obj_ArrayList;??
- }??
?
運(yùn)行結(jié)果:
轉(zhuǎn)載于:https://www.cnblogs.com/qinjunni/archive/2012/02/20/2359181.html
總結(jié)
以上是生活随笔為你收集整理的转 java c++互传arraylist的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 岁月是一把刀是哪首歌啊?
- 下一篇: 一滴两滴下一句是什么呢?