JNI中C調用Java方法

背景需求java

  咱們須要在JNI的C代碼調用Java代碼。實現原理:使用JNI提供的反射藉口來反射獲得Java方法,進行調用。ide

JNI關鍵方法講解。函數

1. 在同一個類中,調用其餘方法spa

JNIEXPORT void JNICALL Java_cn_itcast_ndkcallback_DataProvider_callmethod1
  (JNIEnv * env, jobject obj){
    //在c代碼裏面調用java代碼裏面的方法
    // java 反射
    //1 . 找到java代碼的 class文件
    //    jclass      (*FindClass)(JNIEnv*, const char*);
    jclass dpclazz = (*env)->FindClass(env,"cn/itcast/ndkcallback/DataProvider");
    if(dpclazz==0){
        LOGI("find class error");
        return;
    }
    LOGI("find class ");

    //2 尋找class裏面的方法
    //   jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
    jmethodID method1 = (*env)->GetMethodID(env,dpclazz,"helloFromJava","()V");
    if(method1==0){
        LOGI("find method1 error");
        return;
    }
    LOGI("find method1 ");
    //3 .調用這個方法
    //    void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
    (*env)->CallVoidMethod(env,obj,method1);
}

 注意: 看紅色的內容,如何得到呢? 這個是函數的簽名。函數簽名借住命令 javap -p -s(這兩個參數必定要加入)來得到,放到第二個參數便可。code

注意:blog

1. 要加入上面的參數 -p -sstring

2. signature後面有時候帶「;」,不要丟掉。 主要要仔細檢查it

示例:ast

void notifyOnStatusReport(int32_t status)
{
    if (curEnv != NULL && curObj != NULL) {
        jclass clsstring = curEnv->FindClass("com/baidu/tieba/liveSdk/publisher/LiveNativeSender");
        jfieldID mUsercommandCallbackEventListnerFieldId = curEnv->GetFieldID(clsstring,"mStatusEventListener","Lcom/baidu/tieba/liveSdk/publisher/OnStatusEventListener;");
        jobject mUsercommandCallbackEventListner = curEnv->GetObjectField(curObj,mUsercommandCallbackEventListnerFieldId);
        
        jclass onStatusEventListenerClsstring = curEnv->FindClass("com/baidu/tieba/liveSdk/publisher/OnStatusEventListener");
        jmethodID onStatusReport = curEnv->GetMethodID(onStatusEventListenerClsstring, "onStatusReport",
                                         "(I)V");
        curEnv->CallVoidMethod(mUsercommandCallbackEventListner, onStatusReport, status);
    }
}

 

這樣就能夠調用DataProvider中的helloFromJava方法了。class

2. 上面的方法是調用的返回值爲void的java方法。若是想調用其餘類型的。JNI中還提供的許多其餘返回類型的方法。

    jobject     (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);
    jobject     (*CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jobject     (*CallObjectMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jboolean    (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...);
    jboolean    (*CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jboolean    (*CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jbyte       (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...);
    jbyte       (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jbyte       (*CallByteMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jchar       (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...);
    jchar       (*CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jchar       (*CallCharMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jshort      (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...);
    jshort      (*CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jshort      (*CallShortMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jint        (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
    jint        (*CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jint        (*CallIntMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jlong       (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...);
    jlong       (*CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jlong       (*CallLongMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jfloat      (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...) __NDK_FPABI__;
    jfloat      (*CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list) __NDK_FPABI__;
    jfloat      (*CallFloatMethodA)(JNIEnv*, jobject, jmethodID, jvalue*) __NDK_FPABI__;
    jdouble     (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...) __NDK_FPABI__;
    jdouble     (*CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list) __NDK_FPABI__;
    jdouble     (*CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, jvalue*) __NDK_FPABI__;
    void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
    void        (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    void        (*CallVoidMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);

 

3. 若是java中的方法是靜態的,就須要調用GetStaticMethodID 和 CallStaticVoidMethod 方法。

JNIEXPORT void JNICALL Java_cn_itcast_ndkcallback_DataProvider_callmethod4
  (JNIEnv * env, jobject obj){
      //1 . 找到java代碼的 class文件
        //    jclass      (*FindClass)(JNIEnv*, const char*);
        jclass dpclazz = (*env)->FindClass(env,"cn/itcast/ndkcallback/DataProvider");
        if(dpclazz==0){
            LOGI("find class error");
            return;
        }
        LOGI("find class ");

        //2 尋找class裏面的方法
        //   jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
        // 注意 :若是要尋找的方法是靜態的方法 那就不能直接去獲取methodid
        //jmethodID method4 = (*env)->GetMethodID(env,dpclazz,"printStaticStr","(Ljava/lang/String;)V");
        //    jmethodID   (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*);
        jmethodID method4 = (*env)->GetStaticMethodID(env,dpclazz,"printStaticStr","(Ljava/lang/String;)V");
        if(method4==0){
            LOGI("find method4 error");
            return;
        }
        LOGI("find method4 ");

        //3.調用一個靜態的java方法
        //    void        (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);
        (*env)->CallStaticVoidMethod(env,dpclazz,method4,(*env)->NewStringUTF(env,"static haha in c"));
}

 

4. 若是C調用的Java方法不在一個類中。

分析:JNI提供的方法都有兩個參數:(JNIEnv *env , jobject obj)。 env是JNI提供的方法集合。 obj是上線文。下面的例子的obj不是所須要的上下午,因此要從新建立。

 

//obj DemoActivity
 JNIEXPORT void JNICALL Java_cn_itcast_ndkcallback_DemoActivity_call_1dp_1method1
  (JNIEnv * env, jobject obj){
    //在c代碼裏面調用java代碼裏面的方法
        // java 反射
        //1 . 找到java代碼的 class文件
        //    jclass      (*FindClass)(JNIEnv*, const char*);
        jclass dpclazz = (*env)->FindClass(env,"cn/itcast/ndkcallback/DataProvider");
        if(dpclazz==0){
            LOGI("find class error");
            return;
        }
        LOGI("find class ");

        //2 尋找class裏面的方法
        //   jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
        jmethodID method1 = (*env)->GetMethodID(env,dpclazz,"helloFromJava","()V");
        if(method1==0){
            LOGI("find method1 error");
            return;
        }
        LOGI("find method1 ");
        //3 .調用這個方法
        //    void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
        //    jobject     (*NewObject)(JNIEnv*, jclass, jmethodID, ...);
        //  jobject     (*AllocObject)(JNIEnv*, jclass);
        jobject dpobj= (*env)->AllocObject(env,dpclazz);

        (*env)->CallVoidMethod(env,dpobj,method1);
}

 

5. 提示

爲了不4中的內容,咱們儘可能讓C要調用的Java方法在同一個類中

相關文章
相關標籤/搜索