步骤 4:编写 C/C++ 代码
当谈到编写 C/C++ 函数实现时,有一点需要牢记:说明必须和 JNI_javaCallc_test.h 的函数声明完全一样。
我们将研究用于 C 实现和 C++ 实现的完整代码,然后讨论两者之间的差异。
C函数实现以下是 JNI_javaCallc_test.c,它是用 C 编写的实现:
#include <jni.h>
/* Header for class test_JNI_javaCallc_test */
/*
* Class: test_JNI_javaCallc_test
* Method: intMethod
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_test_JNI_1javaCallc_1test_intMethod(JNIEnv *env, jobject obj, jint num)
{
return num * num;
}
/*
* Class: test_JNI_javaCallc_test
* Method: booleanMethod
* Signature: (Z)Z
*/
JNIEXPORT jboolean JNICALL Java_test_JNI_1javaCallc_1test_booleanMethod
(JNIEnv *env, jobject obj, jboolean boolean) {
return!boolean;
}
/*
* Class: test_JNI_javaCallc_test
* Method: stringMethod
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_test_JNI_1javaCallc_1test_stringMethod
(JNIEnv *env, jobject obj, jstring string)
{
const char *str = (*env)->GetStringUTFChars(env, string, 0);
char cap[128];
strcpy(cap, str);
(*env)->ReleaseStringUTFChars(env, string, str);
return (*env)->NewStringUTF(env, strupr(cap));
}
/*
* Class: test_JNI_javaCallc_test
* Method: intArrayMethod
* Signature: ([I)I
*/
JNIEXPORT jint JNICALL Java_test_JNI_1javaCallc_1test_intArrayMethod
(JNIEnv *env, jobject obj, jintArray array)
{
int i, sum = 0;
jsize len = (*env)->GetArrayLength(env, array);
jint*body = (*env)->GetIntArrayElements(env, array, 0);
for(i=0; i<len; i++)
{ sum += body[i];
}
(*env)->ReleaseIntArrayElements(env, array, body, 0);
return sum;
}
C++ 函数实现
#include <jni.h>
/* Header for class test_JNI_javaCallc_test */
/*
* Class: test_JNI_javaCallc_test
* Method: intMethod
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_test_JNI_1javaCallc_1test_intMethod(JNIEnv *env, jobject obj, jint num)
{
return num * num;
}
/*
* Class: test_JNI_javaCallc_test
* Method: booleanMethod
* Signature: (Z)Z
*/
JNIEXPORT jboolean JNICALL Java_test_JNI_1javaCallc_1test_booleanMethod
(JNIEnv *env, jobject obj, jboolean boolean) {
return!boolean;
}
/*
* Class: test_JNI_javaCallc_test
* Method: stringMethod
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_test_JNI_1javaCallc_1test_stringMethod
(JNIEnv *env, jobject obj, jstring string)
{
constchar *str = env->GetStringUTFChars(string, 0);
char cap[128];
strcpy(cap, str);
env->ReleaseStringUTFChars(string, str);
returnenv->NewStringUTF(strupr(cap));
}
/*
* Class: test_JNI_javaCallc_test
* Method: intArrayMethod
* Signature: ([I)I
*/
JNIEXPORT jint JNICALL Java_test_JNI_1javaCallc_1test_intArrayMethod
(JNIEnv *env, jobject obj, jintArray array)
{
int i,sum = 0;
jsizelen = env->GetArrayLength(array);
jint*body = env->GetIntArrayElements(array, 0);
for(i=0; i<len; i++)
{
sum += body[i];
}
env->ReleaseIntArrayElements(array, body, 0);
returnsum;
}
C 和 C++ 函数实现的比较
唯一的差异在于用来访问 JNI 函数的方法。
在C中,JNI 函数调用由“(*env)->”作前缀,目的是为了取出函数指针所引用的值。
在 C++ 中,JNIEnv 类拥有处理函数指针查找的内联成员函数。
下面将说明这个细微的差异,其中,这两行代码访问同一函数,但每种语言都有各自的语法
C语法: jsize len = (*env)->GetArrayLength(env,array);
C++语法: jsize len =env->GetArrayLength(array);