学习一门新的编程语言,数据类型是最基本的东西,这里我们讲述下jni中的数据类型。
在JNI中把数据类型分为3类:
primitive type:int float char
reference type:class instances arrays
string type
在上一篇HelloWorld中我们打印出HelloWorld等字样,我们没有传入任何参数,这里先给出一个例子,我们在java端传入字符串,然后看在jni中时如何做处理的。
这个例子跟之前的Helloworld差不多,稍作修改,我们在java端传入参数,
新建一个类,专门用来封转jni的method:
~~~
package com.android.jni;
public class Prompt {
public native String getLine(String prompt);
static {
System.loadLibrary("MyJNI");
}
}
~~~
在主activity中调用:
~~~
//调用原生函数得到字符串str
Prompt pmt = new Prompt();
String str=pmt.getLine("Put in a line!");
//吐出message
Toast.makeText(mContext, str, Toast.LENGTH_SHORT).show();
~~~
我们调用了Prompt中的getLine方法。
然后看下C中的代码:
~~~
jstring
Java_com_android_jni_Prompt_getLine(JNIEnv* env,jobject jobj,jstring prompt)
{
char buf[128];
const jbyte *str;
str = (*env)->GetStringUTFChars(env,prompt,NULL);
if(str == NULL)
return NULL;
__android_log_print(ANDROID_LOG_INFO,"-JNI-","%s",str);
(*env)->ReleaseStringUTFChars(env,prompt,str);
sprintf(buf,"From C + %s",str);
return (*env)->NewStringUTF(env,buf);
}
~~~
getLine函数呼叫了JNI的功能函数GetStringUFTChars来读取我们传入的prompt字符串(java端)。GetStringUFTChars函数进入JNIEnv 结构指针,把java中的UTF-8字符类型转变成C中的Unicode sequence,转换成jstring 参考来使用。
最后在释放str的时候不要忘记检查str是否为空,因为GetStringUFTChars函数可能会调用失败(outofmenory)。
当原生代码把传进来的UTF-8类型字符串之后应该立即释放内存调用ReleaseStringUTFChars。
调用NewStringUTF函数来构建新的字符串return给java代码。
在模拟器中运行,当我们点击按钮的时候会出现字符串,“From C + 。。。”
![](https://box.kancloud.cn/2016-08-03_57a197f80697f.gif)
调用成功。
---------------------------------------------------------------------------------
下面我们来进入数组,先看下面的数组定义:
int[] iarr;
float[] farr;
Object oarr;
int[][] arr2;
iarr和farr是数据数组,但是oarr和arr2是对象数组。
下面举个例子进入数据数组:
先看下我们要实现的,在java代码中:
~~~
//调用原生函数得到字符串str
//Prompt pmt = new Prompt();
//String str=pmt.getLine("Put in a line!");
int arr[] = new int[10];
for(int i=0;i<10;i++)
arr[i]=i;
int sum = IntArray.sumArray(arr);
//吐出message
Toast.makeText(mContext, "sum = "+sum, Toast.LENGTH_SHORT).show();
~~~
封装动态库function:
~~~
package com.android.jni;
public class IntArray {
public native static int sumArray(int[] arr);
static {
System.loadLibrary("IntArray");
}
}
~~~
定义一个数组,然后调用jni中的function来对数组进行操作,这边在java代码中传进去的是一个整形的数组。
-----------------------------------------------------------------------------------------------
我们来看下在jni中是如何处理的:
~~~
jint
Java_com_android_jni_Native_sumArray(JNIEnv* env,jobject jobj,jintArray arr)
{
jint buf[10];
jint i, sum = 0;
(*env)->GetIntArrayRegion(env,arr,0,10,buf);
for(i=0;i<10;i++)
sum += buf[i];
return sum;
}
~~~
这里调用了GetIntArrayRegion函数来把传进来的arr数组中的数据都拷贝进C,该函数第三个参数是索引的开始值,第四个参数是被拷贝的数。
JNI也可以使用Get/Release<Type>ArrayElements 函数来使原生代码直接拥有数组的指针。
~~~
jint
Java_com_android_jni_Native_sumArray(JNIEnv* env,jobject jobj,jintArray arr)
{
// jint buf[10];
jint *carr;
jint i, sum = 0;
// (*env)->GetIntArrayRegion(env,arr,0,10,buf);
carr = (*env)->GetIntArrayElements(env,arr,NULL);
if(carr == NULL)
return 0;
for(i=0;i<10;i++)
sum += carr[i];
(*env)->ReleaseIntArrayElements(env,arr,carr,0);
return sum;
}
~~~
运行模拟器:
![](https://box.kancloud.cn/2016-08-03_57a197f822555.gif)
----------------------------------------------------------------------------------------
下面我们来看下jni中对对象数组的处理。
看下原生函数的声明
~~~
public static native int[][] intitInt2DArray(int size);
~~~
下面是jni中的实现
~~~
jobjectArray
Java_com_android_jni_Native_initInt2DArray(JNIEnv *env,
jclass cls,int size)
{
jobjectArray result;
int i;
jclass intArrCls = (*env)->FindClass(env, "[I");
if (intArrCls == NULL) {
return NULL; /* exception thrown */
}
result = (*env)->NewObjectArray(env, size, intArrCls,NULL);
if (result == NULL) {
return NULL; /* out of memory error thrown */
}
for (i = 0; i < size; i++) {
jint tmp[256]; /* make sure it is large enough! */
int j;
jintArray iarr = (*env)->NewIntArray(env, size);
if (iarr == NULL) {
return NULL; /* out of memory error thrown */
}
for (j = 0; j < size; j++) {
tmp[j] = i + j;
}
(*env)->SetIntArrayRegion(env, iarr, 0, size, tmp);
(*env)->SetObjectArrayElement(env, result, i, iarr);
(*env)->DeleteLocalRef(env, iarr);
}
return result;
}
~~~
------------------------------------------------------------------------------------------
ok,我们的基本数据类型就介绍到这,这里数据类型还有很多,大家可以参考user guide,一般我遇到新类型就去翻资料。
下面我们会介绍jni是如何调用java中的成员函数和成员变量的。