在前面我们讲了一下如何使用Java调用C,本文我们讲一下如何使用JNI提供的接口来反射得到Java方法进行调用。
主要步骤如下:
- FindClass (找到Java层的类)
- GetMethodID / GetFieldID (获取Java类中的方法 / Java类中的属性)
- NewObject (创建Java对象)
- Call<TYPE> Method / [G/S]et<Type> Field (调用方法 / 设置属性)
实战
Java层:
package com.renhui.jnihelloworld; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Example of a call to a native method TextView tv = findViewById(R.id.sample_text); tv.setText(stringFromJNI()); } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ public native String stringFromJNI(); // Used to load the 'native-lib' library on application startup. static { System.loadLibrary("native-lib"); } }
C++层:
#include <jni.h> #include <string> #include <iostream> //FindClass (找到Java层的类) // //GetMethodID / GetFieldID (获取Java类中的方法 / Java类中的属性) // //NewObject (创建Java对象) // //Call<TYPE> Method / [G/S]et<Type> Field (调用方法 / 设置属性) #define JNI_CLASS_PATH "com/renhui/jnihelloworld/Student" extern "C" JNIEXPORT jstring JNICALL Java_com_renhui_jnihelloworld_MainActivity_stringFromJNI(JNIEnv *env, jobject /* this */) { // 找到Java层的类 jclass clazz = env->FindClass(JNI_CLASS_PATH); jmethodID jmethod_init_id = env->GetMethodID(clazz, "<init>", "()V"); jmethodID jmethod_set_id = env->GetMethodID(clazz, "setYear", "(I)V"); jmethodID jmethod_get_id = env->GetMethodID(clazz, "getYear", "()I"); jobject obj = env->NewObject(clazz, jmethod_init_id); env->CallVoidMethod(obj, jmethod_set_id, 28); int year = env->CallIntMethod(obj, jmethod_get_id); char tmp[] = {0, }; std::string hello = "Hello World, year = "; sprintf(tmp, "%d", year); hello.append(tmp); return env->NewStringUTF(hello.c_str()); }
运行效果: