java 传递arraylist_转 java c++互传arraylist

我们知道Java是一个运行在虚拟机里面的高级的编程语言,如果要调用系统的动态链接库的话,就要先声明native修饰的方法(类似接口里面的方法),再由C/C++程序来实现(类似实现接口里的方法)。这样Java调用这些native方法就相当于调用了C/C++里面实现了的方法。通常我们把这种机制叫做JNI(Java NativeInterfac),即Java 本地编程接口

Android也同理,要学会在Android上进行NDK开发,首先我们到打好java JNI的基础。现在我们暂时把Android开发丢到一边先,试试在Java之下编译一个C动态链接库,再用Java程序调用。

1)先来个最简单的打印HelloWorld例子:

Java代码(HelloJni.java):

importjava.util.*;

publicclassHelloJni{

static{

System.loadLibrary("hello");

}

publicnativestaticvoidsayHello();

publicstaticvoidmain(String [] args)

{

HelloJni.sayHello();

}

}

生成头文件(HelloJni.h):

先javac HelloJni.java编译你的Java源码,再javah–jni HelloJni生成所需的头文件

头文件内容是这样的:

/* DO NOT EDIT THIS FILE - it is machine generated */

#include 

/* Header for class HelloJni */

#ifndef _Included_HelloJni

#define _Included_HelloJni

#ifdef __cplusplus

extern "C"{

#endif

JNIEXPORT voidJNICALL Java_HelloJni_sayHello (JNIEnv *, jclass);

#ifdef __cplusplus

}

#endif

#endif

实现头文件声明的方法(HelloJni.cpp)

#include "HelloJni.h"

JNIEXPORT voidJNICALL 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

命令参数解析:-I 是指引入java虚拟机的库的路径,-shared 是指编译成动态链接库(共享库) –o 输出文件名(注意,在Linux平台下的动态链接库有一个命名格式:“lib+库名+.so”在java代码里面loadLibrary的时候不要加lib前缀和.so后缀)

由于我这里把这个动态链接库编译放在当前目录下,所以还要设置环境变量LD_LIBRARY_PATH=该so动态链接库所在的目录,才能正常运行

#############################+++华丽的分割线+++###########################

2)好了,可以打印HelloWorld出来后,我们再深入一点点,传入一个int的数,在C/C++代码里面加1后返回。

Java代码(HelloJni.java):

publicclassHelloJni{

static{

System.loadLibrary("hello");

}

publicstaticnativevoidsayHello();

publicnativeintgetInt();

publicnativevoidsetInt(inti);

publicstaticvoidmain(String args[]){

//      HelloJni.sayHello();

HelloJni hello = newHelloJni();

hello.setInt(2);

System.out.println(hello.getInt());

}

}

生成头文件(HelloJni.h):

/* DO NOT EDIT THIS FILE - it is machine generated */

#include 

/* Header for class HelloJni */

#ifndef _Included_HelloJni

#define _Included_HelloJni

#ifdef __cplusplus

extern"C"{

#endif

JNIEXPORT voidJNICALL Java_HelloJni_sayHello (JNIEnv *, jclass);

JNIEXPORT jint JNICALL Java_HelloJni_getInt (JNIEnv *, jobject);

JNIEXPORT voidJNICALL Java_HelloJni_setInt (JNIEnv *, jobject, jint);

#ifdef __cplusplus

}

#endif

#endif

实现头文件声明的方法(HelloJni.cpp)

#include"HelloJni.h"

inti=1;

JNIEXPORT voidJNICALL Java_HelloJni_sayHello

(JNIEnv *env, jclass cls){

printf("HelloWorld/n");

}

JNIEXPORT jint JNICALL Java_HelloJni_getInt

(JNIEnv *env, jobject thiz){

returni;

}

JNIEXPORT voidJNICALL Java_HelloJni_setInt

(JNIEnv *env, jobject thiz,jint ji){

i = ji+1;

}

运行结果:打印2

3)只是传入简单的数据类型不爽,这次让C/C++生成个Java对象返回

Java代码:pojo实体类(User.java)

publicclassUser{

privatelongid;

privateString userName;

privateboolean isMan;

privateintage;

publicUser(){}

publicUser(longid, String userName, boolean isMan,intage) {

super();

this.id = id;

this.userName = userName;

this.isMan = isMan;

this.age = age;

}

publiclonggetId() {

returnid;

}

publicvoidsetId(longid) {

this.id = id;

}

publicString getUserName() {

returnuserName;

}

publicvoidsetUserName(String userName) {

this.userName = userName;

}

publicboolean isMan() {

returnisMan;

}

publicvoidsetMan(boolean isMan) {

this.isMan = isMan;

}

publicintgetAge() {

returnage;

}

publicvoidsetAge(intage) {

this.age = age;

}

}

Java代码(HelloJni.java):

publicclassHelloJni{

static{

System.loadLibrary("userbean");

}

publicstaticnativevoidsayHello();

publicnativeintgetInt();

publicnativevoidsetInt(inti);

publicnativevoidsetUser(String userName);

publicnativeUser getUser();

publicstaticvoidmain(String args[]){

//      HelloJni.sayHello();

HelloJni hello = newHelloJni();

//      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):

#include 

/* Header for class HelloJni */

#ifndef _Included_HelloJni

#define _Included_HelloJni

#ifdef __cplusplus

extern"C"{

#endif

JNIEXPORT voidJNICALL Java_HelloJni_sayHello (JNIEnv *, jclass);

JNIEXPORT jint JNICALL Java_HelloJni_getInt (JNIEnv *, jobject);

JNIEXPORT voidJNICALL Java_HelloJni_setInt (JNIEnv *, jobject, jint);

JNIEXPORT voidJNICALL Java_HelloJni_setUser (JNIEnv *, jobject, jstring);

JNIEXPORT jobject JNICALL Java_HelloJni_getUser  (JNIEnv *, jobject);

#ifdef __cplusplus

}

#endif

#endif

实现头文件声明的方法(HelloJni.cpp)

#include 

#include 

usingnamespacestd;

inti=1;

jobject user;

JNIEXPORT voidJNICALL Java_HelloJni_sayHello

(JNIEnv *env, jclass cls){

printf("HelloWorld/n");

}

JNIEXPORT jint JNICALL Java_HelloJni_getInt

(JNIEnv *env, jobject thiz){

returni;

}

JNIEXPORT voidJNICALL Java_HelloJni_setInt

(JNIEnv *env, jobject thiz,jint ji){

i = ji+1;

}

JNIEXPORT voidJNICALL Java_HelloJni_setUser

(JNIEnv *env, jobject thiz, jstring name){

jclass userClass = env->FindClass("User");

jmethodID userMethod = env->GetMethodID(userClass,"","()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)有些同学可能会说:“返回个Java对象算什么啊,C/C++和Java之间互传复杂对象才好玩呢!”正所谓“不怕做不到,就怕想不到”,我们接着重构一下上面那个例子!

这次我们传包含有User对象的List到C/C++程序里面

Java代码(User.java)

同上。

Java代码(HelloJni.java)

importjava.util.*;

publicclassHelloJni{

static{

System.loadLibrary("userbean");

}

publicnativeintget();

publicnativevoidset(inti);

publicnativevoidsetUser(String userName);

publicnativeUser getUser();

publicnativevoidsetUserList(ArrayList userList);

publicnativeArrayList getUserList();

publicstaticvoidmain(String [] args)

{

HelloJni hello = newHelloJni();

//      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 userList = newArrayList();

for(inti=0;i<10;i++){

User u = newUser((long)(1000+i),"LiangYaotian"+i,true,21);

userList.add(u);

}

hello.setUserList(userList);

userList = null;

userList = hello.getUserList();

System.out.println("ArrayList construct from C++,then Java print it.....");

for(User u : userList){

System.out.println("id:"+u.getId()+"; name:"+u.getUserName());

}

}

}

C头文件(HelloJni.h)

#include 

/* Header for class HelloJni */

#ifndef _Included_HelloJni

#define _Included_HelloJni

#ifdef __cplusplus

extern "C"{

#endif

JNIEXPORT voidJNICALL Java_HelloJni_sayHello (JNIEnv *, jclass);

JNIEXPORT jint JNICALL Java_HelloJni_getInt (JNIEnv *, jobject);

JNIEXPORT voidJNICALL Java_HelloJni_setInt (JNIEnv *, jobject, jint);

JNIEXPORT voidJNICALL Java_HelloJni_setUser (JNIEnv *, jobject, jstring);

JNIEXPORT jobject JNICALL Java_HelloJni_getUser  (JNIEnv *, jobject);

头文件的实现(HelloJni.cpp)

#include"HelloJni.h"

inti=1;

jobject user;

JNIEXPORT jint JNICALL Java_HelloJni_get

(JNIEnv *env, jobject jthiz){

printf("HelloWorld/n");

}

JNIEXPORT voidJNICALL Java_HelloJni_set

(JNIEnv *env, jobject jthiz, jint ji){

i = ji+1;

}

JNIEXPORT voidJNICALL Java_HelloJni_setUser

(JNIEnv *env, jobject jthiz, jstring name){

jclass userClass = env->FindClass("User");

jmethodID userMethod = env->GetMethodID(userClass,"","()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){

returnuser;

}

JNIEXPORT voidJNICALL Java_HelloJni_setUserList

(JNIEnv *env, jobject jthiz, jobject userList){

inti;

//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 object by C++ , then print it...../n");

for(i=0;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;

constchar*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,"","()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,"","()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");

*/

inti;

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);

}

returnobj_ArrayList;

}

运行结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值