摘要:JNI 記錄
Java call C
Step 1: Write the Java Code
建立HelloWorld.java
//HelloWorld.java
public class HelloWorld
{
public native void showHelloWorld();
static {
System.loadLibrary("hello");//呼叫libhello.so
}
public static void main(String[] args){
new HelloWorld().showHelloWorld();
}
}
Step 2: Compile the Java Code
執行javac HelloWorld.java //編譯
Step 3: Create the .h File (這是自動產生出的不要去編輯)
javah -jni HelloWorld //自動產生對應C標頭檔,內容中粗體為C的函式宣告:
執行javac HelloWorld.java //編譯
Step 3: Create the .h File (這是自動產生出的不要去編輯)
javah -jni HelloWorld //自動產生對應C標頭檔,內容中粗體為C的函式宣告:
-d選項可以指定輸出路徑
-jni 表示產生jni標頭檔案
//hello.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: showHelloWorld
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_showHelloWorld
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
Step 4: Write the Native Method Implementation
建立jni.c
//hello.c
#include
#include "HelloWorld.h"
#include
JNIEXPORT void JNICALL
Java_HelloWorld_showHelloworld(JNIEnv *env, jobject obj)
{
printf("Hello world!\n");
return;
}
Step 5: Create a Shared Library
執行
gcc -fPIC -shared -I<jni.h 目錄> -I<jni_md.h目錄> jni.c -o libjni.so
C call Java
C訪問java不能透過函數指標 只能透過通用的參數介面
需要把想要訪問的類別名 函數名稱 參數傳遞給java引擎
訪問Java中函數的流程:
1. 取得Java對象的類別
cls = env -> GetObjectClass(jobject)
2. 取得Java函數的id值
jmethodId mid = env -> GetMethodId(cls, "method_name", "([Ljava/lang/String;)V");
第二個參數為Java中的函數名稱
第三個參數為Java函數的參數和返回值
Java提供javap工具 可以查看Java函數的輸入 返回參數
javap -s com/android/HelloWorld
-s的含義是簽名(Signature) 因為Java允許函數重載 所以不同的參數 返回值代表著不同的函數
3. 找到函數後 就可以使用該函數
env -> CallXXXMethod(jobject, mid, ret);
訪問Java中變數的流程:
1. cls = env -> GetObjectClass(jobject)
取得變數的id值
2. jfieldId fid = env -> GetFiledId(cls, "filed_name", "I");
field_name為Java變數的名稱
第三個參數為變數的類型
3. 取得變數值
value = env -> GetXXXField(env, jobject, fid)
JNIEnv 表示Java環境, jobject 指向呼叫的物件
java: int, long, byte, boolean, char, short, float, double, object
c中表示類型前面加一個j來表示
jclass取得:
jclass FindClass(const char*, clsName);
jclass GetObjectClass(jobject obj);
jclass GetSuperClass(jclass obj);
jclass cls_string = env -> FindClass("java/lang/String") 取得string類型方式
取得方法名:
GetFieldID/GetMethodID
GetStaticFieldID/GetStaticMethodID
Java類型
|
native類型
|
boolean
|
Z
|
byte
|
B
|
char
|
C
|
double
|
D
|
float
|
F
|
int
|
I
|
long
|
L
|
Object
|
‘L’+’package’+’;’
|
short
|
S
|
object ---> Ljava/lang/Sting;
Array ---> [Ljava/lang/object;