版權(quán)聲明:本文為衛(wèi)偉學(xué)習(xí)總結(jié)文章,轉(zhuǎn)載請注明出處!
一、C++主線程調(diào)用Java方法
- 根據(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)
- 通過JVM獲取JniEnv:JNIEnv *env = jvm->AttachCurrentThread(&env,0);
jvm->DetachCurrentThread();
- 通過JVM獲取JniEnv:JNIEnv *env = jvm->AttachCurrentThread(&env,0);
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;
}
