对于基本数据类型,在native层接口看到的参数,对应的都已经转换成native层的数据类型了,只是名字为了好对应,用 typedef 做了转换。
JAVA 的基本数据类型:
数据类型 大小 范围 默认值
byte(字节) 8 -128 - 127 0
shot(短整型) 16 -32768 - 32768 0
int(整型) 32 -2147483648-2147483648 0
long(长整型) 64 -9233372036854477808-9233372036854477808 0
float(浮点型) 32 -3.40292347E+38-3.40292347E+38 0.0f
double(双精度) 64 -1.79769313486231570E+308-1.79769313486231570E+308 0.0d
char(字符型) 16 ‘ \u0000 - u\ffff ’ ‘\u0000 ’
boolean(布尔型) 1 true/false false
JAVA 数据类型对应的JNI数据类型:
/* "cardinal indices and sizes" */
#ifdef HAVE_INTTYPES_H
# include <inttypes.h> /* C99 */
typedef uint8_t jboolean; /* unsigned 8 bits */
typedef int8_t jbyte; /* signed 8 bits */
typedef uint16_t jchar; /* unsigned 16 bits */
typedef int16_t jshort; /* signed 16 bits */
typedef int32_t jint; /* signed 32 bits */
typedef int64_t jlong; /* signed 64 bits */
typedef float jfloat; /* 32-bit IEEE 754 */
typedef double jdouble; /* 64-bit IEEE 754 */
#else
typedef unsigned char jboolean; /* unsigned 8 bits */
typedef signed char jbyte; /* signed 8 bits */
typedef unsigned short jchar; /* unsigned 16 bits */
typedef short jshort; /* signed 16 bits */
typedef int jint; /* signed 32 bits */
typedef long long jlong; /* signed 64 bits */
typedef float jfloat; /* 32-bit IEEE 754 */
typedef double jdouble; /* 64-bit IEEE 754 */
#ifdef HAVE_INTTYPES_H
# include <inttypes.h> /* C99 */
typedef uint8_t jboolean; /* unsigned 8 bits */
typedef int8_t jbyte; /* signed 8 bits */
typedef uint16_t jchar; /* unsigned 16 bits */
typedef int16_t jshort; /* signed 16 bits */
typedef int32_t jint; /* signed 32 bits */
typedef int64_t jlong; /* signed 64 bits */
typedef float jfloat; /* 32-bit IEEE 754 */
typedef double jdouble; /* 64-bit IEEE 754 */
#else
typedef unsigned char jboolean; /* unsigned 8 bits */
typedef signed char jbyte; /* signed 8 bits */
typedef unsigned short jchar; /* unsigned 16 bits */
typedef short jshort; /* signed 16 bits */
typedef int jint; /* signed 32 bits */
typedef long long jlong; /* signed 64 bits */
typedef float jfloat; /* 32-bit IEEE 754 */
typedef double jdouble; /* 64-bit IEEE 754 */
typedef jint jsize;
Java的 String 和 JNI中的 JString 的关系:
#ifdef __cplusplus /* * Reference types, in C++ */ class _jobject {}; class _jstring : public _jobject {}; typedef _jobject* jobject; typedef _jstring* jstring; #else /* not __cplusplus */ typedef void* jobject; typedef jobject jstring; #endif
比如java中的方法:
public native int test(String str, int i, long l, short s, double d, float f, char c);
用 javah 变成 jni的方法后成这样:
JNIEXPORT jint JNICALL Java_com_jni_test_EncodeJNI_test (JNIEnv *env, jobject objThis, jstring str, jint i, jlong l, jshort s, jdouble d, jfloat f, jchar c);
jlong 在 C 里面对应的 long long 类型,有64bit,输出时用 "%lld"
数组的传递:
public native String arrayTest(String[] strArray, int[] iArray, long[] lArray, short[] sArray, double[] dArray, float[] fArray, char[] cArray);
JNIEXPORT jstring JNICALL Java_com_jni_test_EncodeJNI_arrayTest(JNIEnv *env, jobject objThis, jobjectArray strArray, jintArray iArray, jlongArray lArray, jshortArray sArray, jdoubleArray dArray, jfloatArray fArray, jcharArray cArray);
jbooleanArray (*NewBooleanArray)(JNIEnv*, jsize); jbyteArray (*NewByteArray)(JNIEnv*, jsize); jcharArray (*NewCharArray)(JNIEnv*, jsize); jshortArray (*NewShortArray)(JNIEnv*, jsize); jintArray (*NewIntArray)(JNIEnv*, jsize); jlongArray (*NewLongArray)(JNIEnv*, jsize); jfloatArray (*NewFloatArray)(JNIEnv*, jsize); jdoubleArray (*NewDoubleArray)(JNIEnv*, jsize); jboolean* (*GetBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*); jbyte* (*GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*); jchar* (*GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*); jshort* (*GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*); jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*); jlong* (*GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*); jfloat* (*GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*); jdouble* (*GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*);
获取数组长度: jsize (*GetArrayLength)(JNIEnv*, jarray);
设置IntArray 的值
void SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize len, const jint* buf)
View Code
#include "com_TestCopyPix_jni.h" //#include other headers JNIEXPORT jintArray JNICALL Java_com_TestCopyPix_jni_ct(JNIEnv *env, jobject obj) { //jdoubleArray inner = (*env)->NewDoubleArray(env, 3); // int i = 1; // jintArray array;//定义数组对象 // array = (*env)-> NewIntArray(env, 10); // for(; i<= 10; i++) // (*env)->SetIntArrayRegion(env, array, i-1, 1, &i); // /* 获取数组对象的元素个数 */ // int len = (*env)->GetArrayLength(env, array); // /* 获取数组中的所有元素 */ // jint* elems = (*env)-> GetIntArrayElements(env, array, 0); // for(i=0; i<len; i++) // printf("ELEMENT %d IS %d\n", i, elems[i]); int i = 1; int a = 20; int b = 200; jintArray array;//定义数组对象 array = (*env)-> NewIntArray(env, 2); (*env)->SetIntArrayRegion(env, array, 0, 1, &a); (*env)->SetIntArrayRegion(env, array, 1, 1, &b); // for(; i<= 2; i++) // (*env)->SetIntArrayRegion(env, array, i-1, 1, &i); /* 获取数组对象的元素个数 */ // int len = (*env)->GetArrayLength(env, array); // /* 获取数组中的所有元素 */ // jint* elems = (*env)-> GetIntArrayElements(env, array, 0); return array; }
View Code
jintArray Java_com_summer_PointerTestActivity_test( JNIEnv* env, jobject thiz,jintArray nums) { //获取传入数组的长度 jsize len = (*env)->GetArrayLength(env, nums); //在java中申请一块内存 以用来将C的数组传输给java程序 jintArray ret=(*env)->NewIntArray(env,len); //获取传入的数组 jint *body = (*env)->GetIntArrayElements(env, nums, 0); int i; for(i=0;i<len;i++) { body[i] *=2; } //将C的数组拷贝给java中的数组 (*env)->SetIntArrayRegion(env,ret,0,len,body); return ret; }
String的处理
Java String不能直接被C++程序使用,需要先用 env->GetStringUTFChars把它转化为UTF编码形式的char*再进行处理。
如:
jboolean isCopy = 0;
str = env->GetStringUTFChars(prompt, &isCopy); //C 中是 (*env)->GetStringUTFChars(env, str, &isCopy); 这里返回的char*有字符串结束符
如果想返回一个java的String类型的话,我们可以通过env->NewStringUTF命令用一个char*来创建一个jstring,然后让该jstring返回就可以。
如:jstring rtstr = env->NewStringUTF(tmpstr);
上面的GetStringUTFChars,ReleaseStringUTFChars,NewStringUTF都是JNI提供的处理String类型的函数,更多的JNI函数请查看jin.h。
注意:在使用完你所转换之后的对象之后,需要显示调用 ReleaseStringUTFChars(JNIEnv*, jstring, const char*)方法,让JVM释放转换成UTF-8的string的对象的空间,如果不显示的调用的话,JVM中会一直保存 该对象,不会被垃圾回收器回收,因此就会导致内存溢出。
下面是访问String的一些方法, C中:
◆const char*GetStringUTFChars(JNIEnv*, jstring, jboolean*); 将jstring转换成为UTF-8格式的char*
◆const jchar* GetStringChars(JNIEnv*, jstring, jboolean*); 将jstring转换成为Unicode格式的char*
◆ void ReleaseStringUTFChars(JNIEnv*, jstring, const char*); 释放指向UTF-8格式的char*的指针
◆void ReleaseStringChars(JNIEnv*, jstring, const jchar*); 释放指向Unicode格式的char*的指针
◆jstring NewStringUTF)JNIEnv*, const char*); 创建一个UTF-8格式的String对象
◆jstring NewString(JNIEnv*, const jchar*, jsize); 创建一个Unicode格式的String对象
◆jsize GetStringUTFLength)(JNIEnv*, jstring); 获取 UTF-8格式的char*的长度
◆jsize GetStringLength)(JNIEnv*, jstring); 获取Unicode格式的char*的长 度