3.1 A Simple Native Method
JNIEXPORT jstring JNICALL Java_Prompt_getLine(JNIEnv *env, jobject this, jstring prompt){
}
JNIEXPORT和JNICALL宏(jni.h头文件定义)确保这个函数会从native库中导出.
3.2 Accessing Strings
3.2.1 Converting to Native Strings
JNIEXPORT jstring JNICALL Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt)
{
char buf[128];
const char *str;
str = (*env)->GetStringUTFChars(env, prompt, NULL);
if (str == NULL) {
return NULL; /* OutOfMemoryError already thrown */
}
printf("%s", str);
(*env)->ReleaseStringUTFChars(env, prompt, str); //Freeing Native String Resources
/* We assume here that the user does not type more than 127 characters */
scanf("%s", buf);
return (*env)->NewStringUTF(env, buf); //Constructing New Strings
}
3.2.4 Other JNI String Functions
UTF-8格式的字符串以'\0'结束,Unicode格式的字符串不以'\0'结束.
(1)UTF-8 char 1字节
GetStringUTFChars/
ReleaseStringUTFChars
(2)Unicode jchar 2字节
GetStringChars/ReleaseStringChars
3.3 Accessing Arrays
分两种情况:
(1)基本元素数组
(2)对象数组.
3.3.1 Accessing Arrays in C
拷贝基本元素数组:
JNIEXPORT jint JNICALL Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)
{
jint buf[10];
jint i, sum = 0;
(*env)->GetIntArrayRegion(env, arr, 0, 10, buf); //arr-->buf
for (i = 0; i < 10; i++) {
sum += buf[i];
}
return sum;
}
GetIntArrayRegion的第三个参数0表示arr的起始索引,第四个参数10表示要拷贝的元素个数.
3.3.2 Accessing Arrays of Primitive Types
获取基本元素数组的指针:
GetIntArrayElements/ReleaseIntArrayElements
JNIEXPORT jint JNICALL Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)
{
jint *carr;
jint i, sum = 0;
carr = (*env)->GetIntArrayElements(env, arr, NULL);
if (carr == NULL) {
return 0; /* exception occurred */
}
for (i=0; i<10; i++) {
sum += carr[i];
}
(*env)->ReleaseIntArrayElements(env, arr, carr, 0);
return sum;
}
3.3.5 Accessing Arrays of Objects
获取/设置对象数组:
GetObjectArrayElement/SetObjectArrayElement
JNIEXPORT jobjectArray JNICALL Java_ObjectArrayTest_initInt2DArray(JNIEnv *env,jclass cls,int size)
{
jobjectArray result;
int i;
jclass intArrCls = (*env)->FindClass(env, "[I"); //int[]!!!
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;
}
如上代码创建一个二维数组,如果size设置为3,二维数组如下:
0 1 2
1 2 3
2 3 4
扩充:根据row和column创建二维数组
JNIEXPORT jobjectArray JNICALL createInt2DArray(JNIEnv *env,
jobject obj,
int size_row,
int size_column)
{
int i,j;
//(1)int[]
jclass intArrCls = (*env)->FindClass(env, "[I"); //可以这么用!!!
if (intArrCls == NULL) {
return NULL; /* exception thrown */
}
//(2)int[size_row][]
jobjectArray result = (*env)->NewObjectArray(env, size_row, intArrCls,NULL);
if (result == NULL) {
return NULL; /* out of memory error thrown */
}
//(3)int[size_row][size_column]
for (i = 0; i < size_row; i++) {
jint line[256]; /* make sure it is large enough! */
jintArray iarr = (*env)->NewIntArray(env, size_column);
if (iarr == NULL) {
return NULL; /* out of memory error thrown */
}
for (j = 0; j < size_row; j++) {
line[j] = i + j;
}
(*env)->SetIntArrayRegion(env, iarr, 0, size_column, line);
(*env)->SetObjectArrayElement(env, result, i, iarr);
(*env)->DeleteLocalRef(env, iarr);
}
//不能在函数返回前删除,应该在外部用完后删除
//(*env)->DeleteLocalRef(env,result); //错
return result;
}