C++通过JNI层回调java函数

jni层连接了C++/C编写的库与java层应用,调用jni层的回调函数可以将底层的数值返还给java层,使应用层可以根据相应的数据信息进行相关的处理,话不多说上代码。

test.h

/* 定义回调函数的methodID */
static jmethodID callback_ID;
/* 定义回调函数函数指针*/
typedef void (*callback_t)(PARAMETER* myStruct);
typedef struct{
/*如果有多个回调函数的话可以进行添加,相应的methodID也需要添加*/
callback_t my_callback;
}CallBack_t;

test.cpp

由于回调函数中需要用到JNIEnv* env,在java层调用jni层中有相应的变量,而在jni调用java层中没有相应的参数,而且该参数是线程相关的,不同线程的不能互相调用。但是JVM是只有一个的,可以声明一个JavaVM *变量,在JNI_onLoad函数中对变量进行保存以备后用。

JavaVM *g_JavaVM; 
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
	JNIEnv *env = NULL;  
	g_JavaVM=vm;
	jint result = -1;  
	if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {    
		goto fail;  
	}  
	if(env == NULL){  
		goto fail;
	}
	if (registerMethods(env) != 0) {  /*方法注册函数*/
		goto fail;  
	}     
	result = JNI_VERSION_1_4;  
fail:  
	return result;  
}

定义回调函数的具体实现:

static CallBack_t mCLCallBack={
	native_callback,
};
native_callback的具体实现为:

#define callback_method_class "xxx/xxx/xxx/xxxCallBack"/*回调类包名*/
#define CLASS_PARAMETER "xxx/xxx/xxxx/xxxxPARA" /*参数类*/
#define CALLBACK_FUNC_NAME "xxxxx_callback" /* 回调的java中方法名*/
#define SIGN_CALLBACK "(Lxxx/xxxx/xxxx/xxxxPARA;)V" /*调用函数的签名,参数为参数类*/
void native_callback(PARAMETERS* myStruct)
{
	int status;
	bool isAttached = false;
	JNIEnv* env = NULL;
	/*回调方法类*/
	jclass clazz;
	/* 结构体对应的参数类*/
	jclass paraclazz;
	/* 回调方法类对应的对象*/
	jobject tempObject;
	/* 结构体参数类对应的对象*/
	jobject paraObject;
	/* 回调方法类构造函数的methodID*/
	jmethodID constructID;
	/* 参数类构造函数的methodID*/
	jmethodID paraID;
	/* 参数类中对应的参数ID*/
	jfieldID mStatusID;
/
	status = g_JavaVM->GetEnv((void**)&env, JNI_VERSION_1_4);
	if(status < 0)
	{
		g_JavaVM->AttachCurrentThread(&env,NULL);		
		isAttached = true;
	}	
	
	clazz=env->FindClass(callback_method_class);
	paraclazz=env->FindClass(CLASS_PARAMETER);
	callback_ID=env->GetMethodID(clazz,CALLBACK_FUNC_NAME,SIGN_CALLBACK);
 /* 回调函数类构造函数ID和对象的获取 */
constructID=env->GetMethodID(clazz,"","()V");
/* 得到回调函数类的对象tempObject以供调用CallVoidMethod*/
 tempObject=env->NewObject(clazz,constructID);
/* 参数类类构造函数ID和对象的获取 */
paraID=env->GetMethodID(paraclazz,"","()V");
/* 同上,获取该参数类的对象,当需要对参数类中的数据进行赋值操作时有用*/
paraObject=env->NewObject(paraclazz,paraID);
/* 获取与结构体PARAMETERS对应的参数类中的int类型成员变量mStatus的jfieldID*/
mStatusID=env->GetFieldID(paraclazz,"matchStatus","I");
/* 将结构体中的数据传给参数类中的变量 */
env->SetIntField(paraObject,mStatusID,myStruct->matchStatus);
/*调用回调方法,参数为一个引用jobject*/
env->CallVoidMethod(tempObject,callback_ID,paraObject);

checkAndClearExceptionFromCallback(env, __FUNCTION__);	
if(isAttached)
	g_JavaVM->DetachCurrentThread();/*释放线程*/
}
 PARAMETER结构体很简单,就一个数据,u32 matchStatus.可以根据需求对结构体进行添加,相应的对应的数据类也要进行添加相应的成员变量。 
  

通过注册函数(这个注册函数需要开放接口给java层调用???)将jni中的该回调函数指针赋值给特定的函数指针,则在特定的需求底下可以向java层传递包含有数据信息的类

xxx/xxx/xxxx/xxxxPARA
在回调函数类中实现对应的回调方法,可提取相应的数据信息。

你可能感兴趣的:(随记)