JNI系列文章:java
Jerry哥人狠話很少,直接講正題。api
C層向Java層通訊數組
// java代碼
/* * 在C中調用次方法,獲取登入的用戶id */
private String getLoginUserId(){
return "100010";
}
複製代碼
// c代碼
// 3. 訪問java方法
JNIEXPORT void JNICALL Java_com_jerry_jnitest_JniTest_accessMethod (JNIEnv *env, jobject jobj) {
// 獲取jclass
jclass cls = (*env)->GetObjectClass(env, jobj);
// 獲取調用方法的jmethodID
jmethodID methodID = (*env)->GetMethodID(env, cls, "getLoginUserId", "()Ljava/lang/String;");
// 調用獲取登陸用戶id的方法
jint value = (*env)->CallIntMethod(env, jobj, methodID);
printf("userId = %s\n", value);
}
複製代碼
// java代碼
// c中調用的java靜態方法
/** * 獲取文件的大小 * @param pathName * @return 文件大小 */
public static long getFileSize(String pathName){
return new File(pathName).length();
}
複製代碼
// 建立和寫入一個字符串到文件中,並返回文件大小
JNIEXPORT jlong JNICALL Java_com_jerry_jnitest_JniTest_createAndWriteFile (JNIEnv *env, jobject jobj, jstring jstr_file_path) {
// 寫入的文件路徑 jstring->c
char *filename = (*env)->GetStringUTFChars(env, jstr_file_path, NULL);
printf("filename: %s\n", filename);
// 建立一個文件, "w"表示寫入權限,文件存在則覆蓋
FILE *fp = fopen(filename, "w");
char *text = "在C中建立一個文件並寫入內容,並返回文件大小";
// c的文件io函數,寫入文件
fputs(text, fp);
// 關閉流
fclose(fp);
// 計算文件的長度,這裏不用c的函數來計算,改用調用java的文件api的方式來計算
// 獲取getFileSize方法所在類的類類型
jclass jcls = (*env)->GetObjectClass(env, jobj);
// 獲取方法的id
jmethodID mid = (*env)->GetStaticMethodID(env, jcls, "getFileSize",
"(Ljava/lang/String;)J");
// 調用方法
jlong file_size = (*env)->CallStaticLongMethod(env, jcls, mid, jstr_file_path);
printf("file_size: %lld", file_size);
// 釋放filename
(*env)->ReleaseStringUTFChars(env, jstr_file_path, filename);
return file_size;
}
複製代碼
這裏我經過C調用了java的文件計算api,由於java計算文件比較簡單,直接File.length()就行了。固然也能夠用c來實現獲取文件的長度大小:函數
// 4. 獲取文件大小
int filesize(FILE *fp) {
int length = 0;
if (fp == NULL) {
return length;
}
// 將文件指針的位置,從新定位文件指針
// 0是偏移量,SEEK_END表示文件的末尾位置
fseek(fp, 0, SEEK_END);
// 返回當前文件指針,相對於文件開頭的位置偏移量,就是文件字節長度
length = ftell(fp);
printf("length = %d\n", length);
return length;
}
複製代碼
小夥伴們確定會有疑問,你這方法的簽名,記不住啊,容易懵逼啊。沒有關係,咱們還能夠用命令的方式生成: post
// 5. 訪問java的構造方法
// 使用java.util.Date得到一個時間戳
JNIEXPORT jobject JNICALL Java_com_jerry_jnitest_JniTest_accessConstructor (JNIEnv *env, jobject jobj) {
// 獲取jclass
jclass cls = (*env)->FindClass(env, "java/util/Date");
// 獲取jmethodID, 構造方法的名字使用<init>
jmethodID contructor_mid = (*env)->GetMethodID(env, cls, "<init>", "()V");
// 調用構造方法,實例化一個Date對象
jobject date_jobj = (*env)->NewObject(env, cls, contructor_mid);
// 調用Date的getTime方法
// 獲取date的jclass
jclass date_cls = (*env)->GetObjectClass(env, date_jobj);
// 獲取getTime的jmethodID
jmethodID getTime_mid = (*env)->GetMethodID(env, date_cls, "getTime", "()J");
// 調用getTime方法
jlong timestamp_jlong = (*env)->CallLongMethod(env, date_jobj, getTime_mid);
printf("timestamp = %lld\n", timestamp_jlong);
return date_jobj;
}
複製代碼
構造方法比較特殊,在獲取jmethodID的時候傳入的方法名是固定的。spa
// 8. java傳入一個數組進行排序後同步
// 比較兩個數的大小
int compare(int *a, int *b) {
return (*a) - (*b);
}
JNIEXPORT void JNICALL Java_com_jerry_jnitest_JniTest_inputSortArray (JNIEnv *env, jobject jobj, jintArray jintArr) {
// 獲取數組中的元素jint*
jint *int_arr = (*env)->GetIntArrayElements(env, jintArr, NULL);
// 獲取數組長度
int length = (*env)->GetArrayLength(env, jintArr);
// 利用快速排序法排列數組
qsort(int_arr, length, sizeof(jint), compare);
// 同步操做後的數組內存到java中
// 最後一個參數mode的解釋
// 0:Java的數組更新同步,而後釋放C/C++的數組內存
// JNI_ABORT:Java的數組不會更新同步,可是釋放C/C++的數組內存
// JNI_COMMIT:Java的數組更新同步,不釋放C/C++的數組內存(可是函數執行完了局部的變量仍是會釋放掉)
(*env)->ReleaseIntArrayElements(env, jintArr, int_arr, 0);
}
複製代碼
ReleaseIntArrayElements這個函數很重要,只有調用了這個函數,C中操做的數組元素,纔會同步到java,不然java中傳入的數組打印後仍是原來的。指針
// 9. C中生成一個數組返回給java
JNIEXPORT jintArray JNICALL Java_com_jerry_jnitest_JniTest_outputArray (JNIEnv *env, jobject jobj, jint len) {
// 建立一個jintArray數組變量
jintArray jint_Arr = (*env)->NewIntArray(env, len);
// 將jintArray轉換成c的jint*指針進行數組賦值
jint *elements = (*env)->GetIntArrayElements(env, jint_Arr, NULL);
int i = 0;
for (; i < len; i++) {
elements[i] = i;
}
// 將C中的建立修改的數組同步到Java中
(*env)->ReleaseIntArrayElements(env, jint_Arr, elements, 0);
return jint_Arr;
}
複製代碼
一樣也要調用ReleaseIntArrayElements函數,去同步操做的數據,java獲取的數組纔會有值,同時釋放掉C/C++的數組內存。code
JNI系列文章:cdn