Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从c++;使用JNI 我试图在java中为一个特定的USB设备包C++库。 该库支持回调函数,以通知应用程序usb设备与PC的连接和分离_Java_C++_Methods_Java Native Interface - Fatal编程技术网

从c++;使用JNI 我试图在java中为一个特定的USB设备包C++库。 该库支持回调函数,以通知应用程序usb设备与PC的连接和分离

从c++;使用JNI 我试图在java中为一个特定的USB设备包C++库。 该库支持回调函数,以通知应用程序usb设备与PC的连接和分离,java,c++,methods,java-native-interface,Java,C++,Methods,Java Native Interface,回调函数必须具有如下特定格式: DWORD callbackFunction(void *params); JNIEnv *env; jvm->AttachCurrentThread((void **)&env, NULL); //your code here jvm->DetachCurrentThread(); 因此,我在JNI dll中实现了这样一个函数,并希望在调用该函数时调用JavaWapper中的函数 问题是我应该使用什么JNIENV从中调用GetObje

回调函数必须具有如下特定格式:

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

//your code here

jvm->DetachCurrentThread();
因此,我在JNI dll中实现了这样一个函数,并希望在调用该函数时调用JavaWapper中的函数

问题是我应该使用什么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是一个接口,它的方法在另一个CALS中实现,即“callBackClass”

您可能需要做的是在C中创建一个队列并等待它或使用Java线程轮询它。这将始终有一个当前的JNIEnv可用


看来你不能

。。。。保存上次JNI调用中的JNIENV,该调用设置了这个函数并重用它

您的回调似乎返回了一些参数,您在设置回调时可能已经传递了这些参数。您可以将其中一个设置为JNIENV。

创建一个jniinit(JNIENV*env,jclass c(或jobject o))并


对于本机关闭/清理,最好也有一个JNI关闭(JNIEnv、jclass(或jobject)),您需要有一个对当前JVM的引用:

JavaVM *jvm;
可以在C++后端添加初始化方法,在程序启动时获得该引用:

JNIEXPORT void JNICALL init(JNIEnv *env, jclass){
    env->GetJavaVM(&jvm);
}
当观察USB连接/分离时,您可以从这个JavaVM获得JNIEnv,如下所示:

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

//your code here

jvm->DetachCurrentThread();

这样,每次USB设备更改都会创建一个新线程。如果您只使用一个线程进行chceking,那么只需要连接一次(可能是在initilizer中),然后只要您的本机线程保持连接到JVM,JNIEnv就会有效。

我也遇到了同样的问题。就好像在初始化方法中创建的对对象的引用在其他方法中没有用处一样。实际上是这样的。
解决方案是初始化对对象的引用,而不是简单地用

callBackObj = callback
但是

callbackObj = env->NewGlobalRef(callback)

这里也有同样的问题:

您通常不应该保存JNIEnv以供以后重新使用,即使它偶尔可以这样做。Java回调应该从一个JVM引用开始,从中可以获得一个适当的JNIEnv指针。你能解释一下在不保存它的情况下是如何做到的吗?第一次进入JNI land时,你会保存一个对VM的引用(参见Jakub的回答)。从VM引用中,您可以稍后检索特定于上下文的JNIEnv指针。是的,保存JNI并稍后使用它会导致访问冲突异常。您好,Jakub。谢谢你的回复。这解决了我的问题。但现在我又遇到了另一个问题。我可以使用从GetJavaVM方法获得的JNIENV参数获取jclass和方法ID,但是在JAVA中调用函数(使用CallVoidMethod)会导致访问冲突异常。我在本机库中为usb设备设置的回调函数在与主线程不同的新线程中调用。通常,要与Java一起使用的每个新线程都必须使用AttachCurrentThread()附加。它将使JVM将此本机线程与线程对象相关联。如果试图从未连接的线程调用Java函数,则会导致访问冲突。发布更多代码,我们将拭目以待。感谢您的评论。我不得不让那件事保持原样,去做另一件事。但是谢谢你的回复。接缝必须是相关的。我(迟早)会查的。顺便问一下,你编辑过你的帖子吗?通知不一样!不客气,顺便说一句,很抱歉迟了答复。我编辑我的帖子了吗?嗯。。。可能是。这是我最初的回答之一,我对回答的格式有一些问题。此外,fbfcn还纠正了我的语法(顺便说一句,我感谢他)。