1. 程式人生 > >NDK[2]Java方法到C方法 和 C方法到Java方法

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) {
       

super.onCreate(savedInstanceState);
       
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);
}