gpt4 book ai didi

java - 使用 JNI 从 C++ 调用 Java 方法

转载 作者:太空狗 更新时间:2023-10-29 20:06:03 29 4
gpt4 key购买 nike

我正在尝试为 JAVA 中的特定 USB 设备包装一个 C++ 库。该库支持回调函数,以通知应用程序有关 USB 设备与 PC 的连接和分离。

回调函数必须有这样的特定格式:

DWORD callbackFunction(void *params);

所以我在 JNI dll 中实现了这样一个函数,并希望在调用此函数时调用 Java wapper 中的函数。

问题是我应该使用什么 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);
}

然后我在 DLL 中为 USB 设备设置了一个回调函数,当我附加设备时它被成功调用。

我放入 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 是一个接口(interface),它的方法是在另一个 calss 中实现的,即“callBackClass”

最佳答案

您需要引用当前的 JVM:

JavaVM *jvm;

可以在C++后台添加一个initilizing方法,在程序启动时获取这个引用:

JNIEXPORT void JNICALL init(JNIEnv *env, jclass){
env->GetJavaVM(&jvm);
}

并且在观察 USB attachemnt/detachment 时,您可以像这样从这个 JavaVM 获取 JNIEnv:

JNIEnv *env;
jvm->AttachCurrentThread((void **)&env, NULL);

//your code here

jvm->DetachCurrentThread();

这是为了让每个 USB 设备更改都创建一个新线程。如果您只使用一个线程进行检查,则只需附加一次(也许在启动器中?),然后只要您的 native 线程保持附加到 JVM,您就可以使 JNIEnv 有效。

关于java - 使用 JNI 从 C++ 调用 Java 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9668938/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com