步驟 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) {inti, 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);