JAVA本地方法呼叫(2)陣列引數傳遞
阿新 • • 發佈:2019-02-06
JAVA可以把陣列作為引數傳遞給本地方法,在本地方法中可以訪問陣列中的元素。
不過,在本地方法卻不能直接訪問傳進來的陣列,需要進行一定的轉換。舉例說明:
1、建立 JAVA 類:
package test; public class Test { public native void copy(int[] a, int[] b); public static void main(String[] args){ System.load("/root/mycodes/native/intArrayCpy/Test.so"); Test obj = new Test(); int[] a = new int[]{1, 2, 3, 4, 5}; int[] b = new int[a.length]; obj.copy(a, b); String pre = "\r\n\r\n"; for(int i : b){ System.out.print(pre + i); pre = ", "; } System.out.println(); } }
2、編譯並生成 .h 檔案:
javac -d . Test.java
javah -jni test.Test
3、編寫 c 源程式,可以將 javah 生成的檔案拷貝成 c 檔案,然後在上面修改:
cp test_Test.h test_Test.c
vim test_Test.c
修改之後的C源程式如下:
#include <jni.h> /* Header for class test_Test */ #ifndef _Included_test_Test #define _Included_test_Test #ifdef __cplusplus extern "C" { #endif /* * Class: test_Test * Method: copy * Signature: ([I[I)V */ JNIEXPORT void JNICALL Java_test_Test_copy (JNIEnv * env, jobject obj, jintArray pA, jintArray pB){ int a[5]; int b[5]; int i; jsize size = (*env)->GetArrayLength(env, pA); (*env)->GetIntArrayRegion(env, pA, 0, size, a); for(i=0; i<5; i++){ b[i] = a[i]; } (*env)->SetIntArrayRegion(env, pB, 0, 5, b); } #ifdef __cplusplus } #endif #endif
4、編譯並執行:
gcc -I/usr/java/jdk1.7.0/include/ -I/usr/java/jdk1.7.0/include/linux -fPIC -shared -o Test.so test_Test.c
java test.Test
注意在 Test.java 檔案中,System.load 中的引數是由上面的 gcc 命令生成的 so 檔案的全路徑
觀察發現,如果要訪問由JAVA虛擬機器傳進來的陣列,必須呼叫 env 提供的函式進行轉換。在 jdk 安裝目錄下查詢 jni.h 檔案,可以發現jdk其實為我們定義了很多轉換函式。比如上面的程式碼中用到了:
GetArrayLength 得到傳入的陣列引數的元素個數
GetIntArrayRegion 將JAVA虛擬機器傳進來的整數陣列元素拷貝到本地的整數陣列
SetIntArrayRegion 將本地的整數陣列拷貝到傳進來的引數中,以便傳回