NDK[2]Java方法到C方法 和 C方法到Java方法
【參考連結】
程式執行時,以主執行緒的main()方法為入口,不停的從一個方法呼叫到另一個方法中,方法返回再繼續呼叫其他的
根據之前JVM的知識,其實就是在不停向棧中壓入棧幀、彈出棧幀
所以既可以在java方法中呼叫C/C++方法,也可以在C/C++方法中呼叫Java方法,只不過這兩種棧是分開維護的。
Java方法到C/C++方法
給一個類定義一個native方法,實現其對應的C/C++方法,在Java中呼叫這個native方法就會去呼叫C/C++方法
這個native方法可以是非static的,其對應方法的前兩個引數的型別為JNIEnv,jobject,
也可以是static的,其對應方法的前兩個引數的型別為JNIEnv,jclass
這些型別都是在jni.h中定義的,其中
JNIEnv,其在C中的定義為結構體JNINativeInterface的指標,後續主要就是使用這個型別中的各種函式指標(指向函式的指標)
jobject,代表呼叫的這個Java物件,jclass,代表呼叫的這個Java類,如果在C/C++中要使用的正是這個物件/這個類,則不用去重新獲取。
C/C++方法到Java方法
在C/++方法中呼叫Java方法,程式碼跟反射有點像,需要先獲取到這個方法,然後再呼叫這個方法。
獲取方法主要通過JNIEnv的如下方法
需要知道這個方法的描述符,這在Class檔案結構中已講過,此外還可以通過先編譯然後執行javap –s指令得到
呼叫方法主要通過JNIEnv的如下方法
以如下程式碼為例
先從Java方法中呼叫到C方法nativeMethod1,然後再去呼叫Java類Test1的某個新建物件的非靜態方法test();
先從Java方法中呼叫到C方法nativeMethod2,然後再去呼叫Java類Test2的靜態方法test();
public class MainActivity extends Activity {
public nativevoid nativeMethod1();
public static native void nativeMothod2();
@Override
protected void onCreate(BundlesavedInstanceState) {
setContentView(R.layout.activity_main);
System.loadLibrary("testtt");
}
public void onClick1(View view){
nativeMethod1();
}
public void onClick2(View view){
nativeMothod2();
}
}
#include "com_example_shadowfaxghh_demo_MainActivity.h"
JNIEXPORT void JNICALL Java_com_example_shadowfaxghh_demo_MainActivity_nativeMethod1
(JNIEnv *env, jobject jobj) {
//呼叫Test1的成員方法test()
//獲取到類
jclass clazz=(*env)->FindClass(env, "com/example/shadowfaxghh/demo/Test1");
//獲取到方法//GetMethodID
jmethodID methodID=(*env)->GetMethodID(env, clazz, "test", "()V");
//建立物件
jobject jobj2=(*env)->AllocObject(env, clazz);
//呼叫方法//CallVoidMethod
(*env)->CallVoidMethod(env, jobj2, methodID);
}
JNIEXPORT void JNICALL Java_com_example_shadowfaxghh_demo_MainActivity_nativeMothod2
(JNIEnv *env, jclass jclazz) {
//呼叫Test2的成員方法test()//靜態
//獲取到類
jclass clazz=(*env)->FindClass(env, "com/example/shadowfaxghh/demo/Test2");
//獲取到方法//GetStaticMethodID
jmethodID methodID=(*env)->GetStaticMethodID(env, clazz, "test", "()V");
//呼叫方法//CallStaticVoidMethod
(*env)->CallStaticVoidMethod(env, clazz, methodID);
}