本节将介绍在JNI编程中如何传递参数和返回值。
首先要强调的是,native方法不但可以传递Java的基本类型做参数,还可以传递更复杂的类型,比如String,数组,甚至自定义的类。jni.h中定义了很多接口供我们操作。
其实在前面章节的例子中,我们已经使用到很多java传递参数给jni的例子,只是没有重点介绍,接下来会对传递几种基本类型参数,string,数组,java自定义对象这些参数介绍。
1. 基本类型的传递
实例1:传递int类型给JNI函数
java代码:
public native int intMethod(int n);
JNI实现代码:
//传递int参数
extern "C"
jint Java_com_honjane_ndkdemo_JNIUtils_intMethod( JNIEnv* env, jobject jobj,jint num){
return num*num;
}
注意:num没有经过转换,直接使用的。对的8中基本数据类型传递都可以直接使用,不需要再转换,而string,数组,对象就不能直接使用了,需要把jni数据结构转换成c,c++的数据结构才能操作。
结果:
传递num = 4;
I/main----intMethod: 16
实例2:传递boolean类型给JNI函数
java层:
public native boolean booleanMethod(boolean bool);
JNI实现:
//传递布尔类型
extern "C"
jboolean Java_com_honjane_ndkdemo_JNIUtils_booleanMethod(JNIEnv* env,jobject jobj,jboolean flag){
return !flag;
}
结果:
flag == true
I/main----booleanMethod: false
这里就介绍2个基本数据类型传参,其他几个类型,可以自行去实现。
2. String参数的传递
Java的String和C++的string是不能对等起来的,不能直接使用,需要通过一些函数转换。
实例3:传递String给JNI函数,把参数拼接到jni字符上,然后给java层使用
java代码:
public native String stringMethod(String text);
JNI实现:
//传递string类型
extern "C"
jstring Java_com_honjane_ndkdemo_JNIUtils_stringMethod(JNIEnv* env,jobject jobj,jstring jstr){
//将jstring类型转换成c++识别的char类型
const char * str = env->GetStringUTFChars(jstr,0);
char c[120] = "lily ";
//调用c++拼接字符函数
strcat(c,str);
//释放
env->ReleaseStringUTFChars(jstr,str);
return env->NewStringUTF(c);
}
我们看到与实例1,2两个不一样,拿到jstring后,通过GetStringUTFChars把java层传过来的参数转换成char指针,然后才能操作。
结果:
text:hello
I/main----stringMethod: lily hello
3. 数组参数的传递
实例4:传递一个int数组给jni,然后实现数字元素求和
java代码:
public native int intArrayMethod(int[] intArray);
JNI实现:
extern "C"
jint Java_com_honjane_ndkdemo_JNIUtils_intArrayMethod(JNIEnv* env,jobject jobj,jintArray jarr){
jint len=0,sum=0;
//获得数组长度
len = env->GetArrayLength(jarr);
//转换数组为int指针
jint* body = env->GetIntArrayElements(jarr,0);
//由于一些版本不兼容,i不定义在for循环中
jint i=0;
for(;i<len;i++){
sum+=body[i];
}
return sum;
}
结果:
arr = {3,5,6,12,46,33};
I/main----intArrayMethod: 105
4. 自定义java对象参数的传递
实例5:传递复杂对象person,再jni函数中新构造一个person传回java层输出
定义Person
public class Person {
private String name;
private int age;
public Person() {
}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Person :{ name: "+name+",age: "+age+"}";
}
}
java层native函数
public native Person objectMethod(Person person);
JNI实现:
//传递person自定义对象给jni函数
extern "C"
jobject Java_com_honjane_ndkdemo_JNIUtils_objectMethod(JNIEnv* env,jobject jobj,jobject jperson){
jclass jcls = env->GetObjectClass(jperson);
// jclass jcls = env->FindClass("com/honjane/ndkdemo/model/Person"); //或反射得Person类引用
if(jcls == NULL){
return env->NewStringUTF("not find class");
}
//得到person对象的构造函数Person(int,string)
jmethodID constrocMID = env->GetMethodID(jcls,"<init>","(ILjava/lang/String;)V");
if(constrocMID == NULL){
return env->NewStringUTF("not find constroc method");
}
jstring str = env->NewStringUTF("honjane");
//构造一个对象,调用该类的构造函数,并且传递参数
jobject new_ojb = env->NewObject(jcls,constrocMID,21,str);
return new_ojb;
}
输出结果:
I/main----objectMethod: Person :{ name:honjane ,age:21}
作者:tsdfk1455 发表于2017/1/1 0:34:14 原文链接
阅读:28 评论:0 查看评论