1. 程式人生 > >(JNI)c程式碼利用反射呼叫java方法

(JNI)c程式碼利用反射呼叫java方法

反射一般分3個步驟:
1.載入calss(位元組碼),獲取class的物件。
2.獲取對應的方法或屬性。
3.修改屬性,或執行方法。

首先回顧一下java中的反射  寫一個類JK:
public class Jk {

     public void p(String s) {
          System. out.println(s);
     }
}
另一個Test類來反射此類,執行p(String)方法:
public class Test {
     public static void main(String[] args) {
           try {
              Class clazz = Test.class.getClassLoader().loadClass("Jk" );
              Method method = clazz.getDeclaredMethod("p" ,
                         new Class[] { String.class });
              method.invoke(clazz.newInstance(), new String[] { "java反射" });
          } catch (Exception e) {
              e.printStackTrace();
          }
     }
}


控制檯輸出:        java反射 c程式碼利用反射呼叫java方法: 目標:在MainActivity中放一個按鈕,點選按鈕,按鈕執行native 方法jk();c語言jk()函式反射執行MainActivity中的jkShow()方法,jkShow()方法彈出Toast。      1.MainActivity.java類
public class MainActivity extends Activity {
     static{
          System. loadLibrary("jk");
     }

     @Override
     protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
          setContentView(R.layout. activity_main);
     }

     public void onclick(View view) {
          jk();
     }

     public native void jk();

     public void jkShow(String message) {
          Toast. makeText(this, message, 0).show();
     }
}

  2.jk.c
#include <jni.h>
//c程式碼利用反射呼叫java方法
JNIEXPORT void JNICALL Java_com_jk184_cj_MainActivity_jk(JNIEnv * env,
           jobject jobj) {
//1.獲取對應的class
//   jclass      (*FindClass)(JNIEnv*, const char*);
     jclass clazz = (*env)-> FindClass(env, "com/jk184/cj/MainActivity" );
//2.獲取對應的方法
     //c語言是獲取方法的id
//   jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
     jmethodID jmID = (*env)-> GetMethodID(env, clazz, "jkShow",
               "(Ljava /lang/String;)V" );
//3.執行方法
//     void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
     (*env)-> CallVoidMethod(env, jobj, jmID,
              (*env)-> NewStringUTF(env, "這是c反射呼叫java方法" ));
}


注意:
(*env)-> GetMethodID(env, clazz, "jkShow",
               "(Ljava /lang/String;)V" );
最有一個引數是方法的簽名,具體規範百度。 可在bin/classes下執行javap -s 類名(com.jk184.cj.MainActivity) 獲得類下面所有方法的簽名。
(*env)-> CallVoidMethod(env, jobj, jmID,
              (*env)-> NewStringUTF(env, "這是c反射呼叫java方法" ));
最後一個使用字串,需要注意兩點: 1.不能直接使用字串 (c和java的型別不一致) 2.使用中文要注意c檔案是UTF-8編碼。(否則亂碼報錯) 第一次寫csdn,初學jni,請抱著懷疑的心態看此文。 最後有錯請指教...