從 Java 呼叫 C 方法
Java 中的靜態和成員方法可以標記為本*機,*以指示它們的實現可以在共享庫檔案中找到。在執行本機方法時,JVM 在載入的庫中查詢相應的函式(請參閱載入本機庫 ),使用簡單的名稱修改方案,執行引數轉換和堆疊設定,然後將控制權移交給本機程式碼。
Java 程式碼
/*** com/example/jni/JNIJava.java **/
package com.example.jni;
public class JNIJava {
static {
System.loadLibrary("libJNI_CPP");
}
// Obviously, native methods may not have a body defined in Java
public native void printString(String name);
public static native double average(int[] nums);
public static void main(final String[] args) {
JNIJava jniJava = new JNIJava();
jniJava.printString("Invoked C++ 'printString' from Java");
double d = average(new int[]{1, 2, 3, 4, 7});
System.out.println("Got result from C++ 'average': " + d);
}
}
C++程式碼
應使用目標類上的 javah
工具生成包含本機函式宣告的標頭檔案。在 build 目錄中執行以下命令:
javah -o com_example_jni_JNIJava.hpp com.example.jni.JNIJava
…生成以下標頭檔案( 為簡潔起見剝離註釋 ):
// com_example_jni_JNIJava.hpp
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h> // The JNI API declarations
#ifndef _Included_com_example_jni_JNIJava
#define _Included_com_example_jni_JNIJava
#ifdef __cplusplus
extern "C" { // This is absolutely required if using a C++ compiler
#endif
JNIEXPORT void JNICALL Java_com_example_jni_JNIJava_printString
(JNIEnv *, jobject, jstring);
JNIEXPORT jdouble JNICALL Java_com_example_jni_JNIJava_average
(JNIEnv *, jclass, jintArray);
#ifdef __cplusplus
}
#endif
#endif
這是一個示例實現:
// com_example_jni_JNIJava.cpp
#include <iostream>
#include "com_example_jni_JNIJava.hpp"
using namespace std;
JNIEXPORT void JNICALL Java_com_example_jni_JNIJava_printString(JNIEnv *env, jobject jthis, jstring string) {
const char *stringInC = env->GetStringUTFChars(string, NULL);
if (NULL == stringInC)
return;
cout << stringInC << endl;
env->ReleaseStringUTFChars(string, stringInC);
}
JNIEXPORT jdouble JNICALL Java_com_example_jni_JNIJava_average(JNIEnv *env, jclass jthis, jintArray intArray) {
jint *intArrayInC = env->GetIntArrayElements(intArray, NULL);
if (NULL == intArrayInC)
return -1;
jsize length = env->GetArrayLength(intArray);
int sum = 0;
for (int i = 0; i < length; i++) {
sum += intArrayInC[i];
}
env->ReleaseIntArrayElements(intArray, intArrayInC, 0);
return (double) sum / length;
}
輸出
執行上面的示例類會產生以下輸出:
從 Java 呼叫 C++‘printString’
得到 C++‘average’的結果:3.4