C++ 全局調(diào)用Java方法

版權(quán)聲明:本文為衛(wèi)偉學(xué)習(xí)總結(jié)文章,轉(zhuǎn)載請注明出處!
一、C++主線程調(diào)用Java方法

    1. 根據(jù)jobject獲取jclass(靜態(tài)方法就不用這一步了)如: jclass clz = env->GetObjectClass(jobj);
  • 2.獲取jmethodid 如:jmethodid jmid = env->GetMethodID(clz,"onError","(ILjava/lang/String;)V");
  • 3.調(diào)用方法如: jenv->CallVoidMethod(jobj,jmid,code,jmsg)

簽名方法參數(shù)類型對應(yīng)表

Java類型 類型簽名
boolean Z
byte B
char C
short S
int I
long L
float F
double D
L全限定名;,比如String,其簽名為Ljava/lang/util/String;
數(shù)組 [類型簽名,比如[B

通過命令獲取native方法簽名
在native所在類的class文件目錄下,執(zhí)行命令:
javap -s ***.class


二、C++子線程調(diào)用Java方法
由于JniEnv是線程相關(guān)的,所以子線程中不能使用創(chuàng)建線程的JniEnv;而JVM是進(jìn)程相關(guān)的,所以可以通過JVM來獲取當(dāng)前線程的JniEnv,然后就可以調(diào)用Java的方法了。

  • 1.獲取JVM對象: JNI_OnLoad(JavaVM* vm, void *reserved)
    1. 通過JVM獲取JniEnv:JNIEnv *env = jvm->AttachCurrentThread(&env,0);
      jvm->DetachCurrentThread();

C++全局調(diào)用Java方法Demo

//
// Created by weiwei on 2019/11/9.
//
#include "jni.h"

#ifndef MYMUSIC_JAVALISTENER_H
#define MYMUSIC_JAVALISTENER_H


class JavaListener {

public:
JavaVM *jvm;
_JNIEnv *jenv;
jobject jobj;
jmethodID  jmid;

public:
JavaListener(JavaVM *vm, _JNIEnv *env, jobject obj);
~JavaListener();

/**
 * 1:主線程
 * 2:子線程
 * @param type
 * @param code
 * @param msg
 */
void onError(int type, int code, const char *msg);

};


#endif //MYMUSIC_JAVALISTENER_H

JavaListener.cpp文件

//
// Created by weiwei on 2019/11/9.
//
#include "JavaListener.h"

JavaListener::JavaListener(JavaVM *vm, _JNIEnv *env, jobject obj) {

   jvm = vm;
   jobj = obj;
   jenv = env;
   jclass cls = env->GetObjectClass(jobj);

   if(!cls) {
      return;
   }

   jmid = env->GetMethodID(cls,"onError","(ILjava/lang/String;)V");

   if(!jmid)
     return;

}

void JavaListener::onError(int type, int code, const char *msg) {

   if(type == 0)
   {
  JNIEnv *env;
  jvm->AttachCurrentThread(&env, 0);
  jstring jmsg = env->NewStringUTF(msg);
  env->CallVoidMethod(jobj, jmid, code, jmsg);
  env->DeleteLocalRef(jmsg);

  jvm->DetachCurrentThread();
  }
  else if(type == 1)
 {
  jstring jmsg = jenv->NewStringUTF(msg);
  jenv->CallVoidMethod(jobj, jmid, code, jmsg);
  jenv->DeleteLocalRef(jmsg);
 }
} 

JNI實現(xiàn)代碼

#include <jni.h>
#include <string>
#include <android/log.h>
#include "pthread.h"
#include "AndroidLog.h"

extern "C"
{
    #include <libavformat/avformat.h>
}

#include "queue"
#include "unistd.h"

pthread_t produc;
pthread_t custom;
pthread_mutex_t mutex;
pthread_cond_t cond;

#include "JavaListener.h"

JavaVM *jvm;
JavaListener *javaListener;

pthread_t childThread;

void *childCallback(void *data) {
   JavaListener *javaListener1 = (JavaListener *) data;

   javaListener1->onError(0,101,"c++ call java meid from child thread! haha");
   pthread_exit(&childThread);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_day1_jado_mymusic_ThreadDemo_callbackFromC(JNIEnv *env, jobject instance) {
   javaListener = new JavaListener(jvm,env,env->NewGlobalRef(instance)); //得到全局的 instance
    //javaListener->onError(1,100,"c++ call java meid from main thread!");
   pthread_create(&childThread, NULL, childCallback, javaListener);
}

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void* reserved)
{
   JNIEnv *env;
   jvm = vm;
   if(vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK)
   {
    return -1;
   }
   return JNI_VERSION_1_6;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 什么是JNI? JNI 是java本地開發(fā)接口.JNI 是一個協(xié)議,這個協(xié)議用來溝通java代碼和外部的本地代碼(...
    a_tomcat閱讀 2,885評論 0 54
  • 0.要素1.類操作2.異常操作3.全局及局部引用4.對象操作5.字符串操作6.數(shù)組操作7.訪問對象的屬性和方法7....
    MagicalGuy閱讀 1,450評論 0 2
  • C++主線程調(diào)用Java方法 主要步驟 1、根據(jù)jobject獲取jclass(靜態(tài)方法就不用這一步了),如: 2...
    張俊峰0613閱讀 279評論 0 0
  • 本系列文章如下: Android JNI(一)——NDK與JNI基礎(chǔ)Android JNI學(xué)習(xí)(二)——實戰(zhàn)JNI...
    隔壁老李頭閱讀 66,859評論 11 90
  • JNI編程 JNI是一種本地編程接口。它允許運行在JAVA虛擬機(jī)中的JAVA代碼和用其他編程語言,諸如C語言、C+...
    微塵_8957閱讀 556評論 0 0

友情鏈接更多精彩內(nèi)容