简体   繁体   English

如何实现从Java调用到C ++的回调函数?

[英]How to implement a callback function that calls from Java to C++?

I have a native C++ application that creates a JVM via JNI, instantiates a Java class (an Akka Actor) and invokes asynchronous non-blocking functions on it. 我有一个本机C ++应用程序,该应用程序通过JNI创建JVM,实例化Java类(Akka Actor),并在其上调用异步非阻塞函数。 I do this using JNI in C++ see snippet below. 我使用C ++中的JNI进行此操作,请参见下面的代码段。

Now I need to be notified in C++ when an Akka response arrives to my Akka Actor. 现在,当Akka响应到达我的Akka Actor时,我需要在C ++中得到通知。 For this I need to pass a native function pointer to Java so that the Akka Java Actor can callback to C++ when the response arrives. 为此,我需要将本机函数指针传递给Java,以便Akka Java Actor可以在响应到达时回调到C ++。 How can I do that? 我怎样才能做到这一点?

Note that using thread synchronization primitives within the Akka Actor would be completely wrong because the Actor would not be able to receive messages if blocked awaiting for some monitor eg a CountDownLatch . 请注意,在Akka Actor中使用线程同步原语将是完全错误的,因为如果Actor被阻止等待某些监视器(例如CountDownLatch则Actor将无法接收消息。

JavaVM* jvm = NULL;
JNIEnv *env = NULL;
JavaVMInitArgs vm_args;
JavaVMOption* options = new JavaVMOption[1];
options[0].optionString = "-Djava.class.path=/home/azg/code/hpcmom/target/1.1.9-SNAPSHOT/hpcmom-cmaes/hpcmom-cmaes-1.1.9-SNAPSHOT.jar";
vm_args.version = JNI_VERSION_1_6;
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = JNI_TRUE;
JNI_GetDefaultJavaVMInitArgs(&vm_args);

// create JVM
JNI_CreateJavaVM(&jvm, (void**) &env, &vm_args);
if (jvm == NULL) {
    throw std::runtime_error("failed creating JVM");
} else {
    log_info << "succeeded creating JVM";
}

// find CmaesClient class
jclass cmaesClass = env->FindClass("com/sfoam/hpcmom/cmaes/CmaesClient");
if (cmaesClass == NULL) {
    throw std::runtime_error("failed finding CmaesClient class");
} else {
    log_info << "succeeded finding CmaesClient class";
}

In your native code, store the address of your callback function in a long. 在您的本机代码中,长时间存储您的回调函数的地址。 Pass the long to your Java code and store it there, as a long. 将long传递给Java代码并将其存储在那里。

When its time for the callback to occur, have Java pass the function's address as a long into a native JNI function. 当发生回调的时间到了,让Java将函数的地址尽可能长地传递给本地JNI函数。

In the native JNI function, cast the long as a function pointer, and invoke it. 在本机JNI函数中,将long转换为函数指针,然后调用它。

I have a nasty solution! 我有一个讨厌的解决方案! You don't actually need a native function pointer. 您实际上不需要本机函数指针。 The actor could just call a method of it's own which is implemented in native code. 参与者可以调用自己的方法,该方法以本机代码实现。

For instance 例如

class CPPNotifyUtil {

    static
    {
        System.loadLibrary ("nastylib");
    }

    public native void notifyCPP(); // implement in CPP   

}

Note that would involve creating another native library (nasty) which your application links to. 请注意,这将涉及创建您的应用程序链接到的另一个本机库(讨厌的)。 This would then be an entry point into your dll, but not your main application. 这将是进入dll的入口点,而不是主应用程序。 You would need to have a method in your native dll that allows you to register listiners to get back to where you want to be notified. 您将需要在本机dll中有一个方法,该方法允许您注册listiners以返回到要通知的位置。

Just make sure that any class calling the native method and your main application are located on the same computer. 只要确保任何调用本机方法的类和您的主应用程序位于同一台计算机上即可。 This goes for any solution. 这适用于任何解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM