回调函数必须具有以下特定格式:
DWORD callbackFunction(void *params);
所以我在JNI dll中实现了这样一个函数,并希望每当调用该函数时,调用Java包装器中的一个函数。
问题是我应该使用哪个JNIENV来调用GetObjectClass、GetMethodID和CallVoidMethod呢?
这是我初始化DLL的方式。"Set(AttachDetach)Callback"方法接受回调函数(第一个参数)和void*参数(第二个参数),在检测到模块附加/分离时将传递给该函数。
JNIEXPORT void JNICALL Java_MyPackage_MyClass_InitializeDLL
(JNIEnv *env, jobject obj, jobject callback)
{
// Storing callback object in global variable.
callBackObj = callback;
env->GetJavaVM(&jvm);
MyInstance = new MyClass();
MyInstance ->SetAttachCallback(AttachCallBack, &callBackObj);
MyInstance ->SetDetachCallback(DetachCallBack, &callBackObj);
// Testing!
jclass callBackCls = env->FindClass("MyPackage/MyClassCallBacks");
jmethodID mid = env->GetMethodID(callBackCls, "attach", "(B)V");
if (!mid)
return ; /* method not found */
//This call here works well
env->CallVoidMethod(callBackObj, mid, 5);
}
然后我在USB设备的DLL中设置了一个回调函数,在我连接设备时它成功地被调用。
我放置在USB设备附加回调中的代码如下:
DWORD CALLBACK AttachCallBack(CallbackParams* params)
{
JNIEnv *env;
jvm->AttachCurrentThread((void **)&env, NULL);
jclass callBackCls = env->FindClass("MyPackage/MyClassCallBacks");
jmethodID mid = env->GetMethodID(callBackCls, "attach", "(B)V");
if (!mid)
return -1; /* method not found */
// This call fails with an access violation Exception
env->CallVoidMethod(*((jobject *)(params->param)), mid, params->moduleIndex);
// This fails the same way too
env->CallVoidMethod(callBackObj, mid, 5);
jvm->DetachCurrentThread();
return 0;
}
在使用AttachCurrentThread之前,我根本无法使用JNIENV指针。但现在除了调用CallVoidMethod之外,对该指针的任何其他使用都是成功的。您看到这里有什么问题吗?
让我补充一下,MyPackage.MyClassCallBacks是一个接口,它的方法在另一个类中实现,即“callBackClass”。