Java呼叫庫檔案(JNI)(android對此有所改變)
阿新 • • 發佈:2019-02-03
1.準備java 程式
testdll.java,內容為:
public class testdll {
static {
System.loadLibrary("goodluck"); //載入庫名,庫的副檔名字究竟是DLL還是SO,由系統自己判斷。
}
//還需對將要呼叫的方法做本地宣告,關鍵字為native。且只需要宣告,而不需要具體實現
public native static int get();
public native static void set(int i);
public static void main(String[] args) {
testdll test = new testdll();
test.set(10);
System.out.println(test.get());
}
}
然後編譯該JAVA程式檔案,生成CLASS,再用JAVAH命令,JNI就會生成C/C++的標頭檔案。
用javac testdll.java編譯它,會生成testdll.class。
再用javah testdll,則會在當前目錄下生成testdll.h檔案,內容如下:
#include
#ifndef _Included_testdll
#define _Included_testdll
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
在具體實現的時候,我們只關心兩個函式原型
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass); 和
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);
這裡JNIEXPORT和JNICALL都是JNI的關鍵字,函式的名稱是JAVA_再加上java程式的package路徑再加函式名組成的。
下面我們用testdll.cpp檔案具體實現這兩個函式;
#include "testdll.h"
int i = 0;
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)
{
return i;
}
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j)
{
i = j;
}
編譯連線成庫檔案,本例是在WINDOWS下做的,生成的是DLL檔案,名字為goodluck.dll。把goodluck.dll拷貝到testdll.class的目錄下(或者加入環境變數中),java testdll執行它。
對於最重要得引數傳遞,字長不一樣,因此,需要轉換。比如傳遞字串,java檔案中引數為byte[] param,c檔案中為jbyteArray,轉換可以如下進行:
jsize theArrayLengthJ = (*env)->GetArrayLength(env,param); //得到本地字長
jbyte * arrayBody = (*env)->GetByteArrayElements(env,param,0);//得到本地元素
char* str=(char *)arrayBody;
main中:
byte[] temp = {0}; //字串末尾補0
String str= "早上好";
byte[] bb= str.getBytes("gbk");
byte[] lastBB = new byte[str.length + temp.length]; //得到最終要傳遞得引數
就是在傳遞位元組陣列到C程式中時,最後的結尾一定要以0結束。