我有一个本机C ++应用程序,它通过JNI创建一个JVM,实例化一个Java类(一个Akka Actor)并在其上调用异步非阻塞函数。我在C ++中使用JNI执行此操作,请参阅下面的代码段。
现在,当Akka回复到达我的Akka Actor时,我需要在C ++中得到通知。为此,我需要将一个本机函数指针传递给Java,以便Akka Java Actor可以在响应到达时回调到C ++。我怎样才能做到这一点?
请注意,在Akka Actor中使用线程同步原语是完全错误的,因为如果阻塞等待某个监视器,则Actor将无法接收消息,例如一个CountDownLatch
。
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";
}
答案 0 :(得分:1)
在您的本机代码中,将回调函数的地址存储为long。将long传递给Java代码并将其存储在那里,很长一段时间。
当回调发生的时候,让Java将函数的地址作为long传递给本机JNI函数。
在本机JNI函数中,将long转换为函数指针,然后调用它。
答案 1 :(得分:1)
我有一个讨厌的解决方案!您实际上并不需要本机函数指针。演员可以调用它自己的方法,用本机代码实现。
例如
class CPPNotifyUtil {
static
{
System.loadLibrary ("nastylib");
}
public native void notifyCPP(); // implement in CPP
}
请注意,这将涉及创建应用程序链接到的另一个本机库(讨厌)。这将是您的dll的入口点,但不是您的主要应用程序。您需要在本机dll中使用一种方法,允许您注册列表器以返回到您希望收到通知的位置。
确保调用本机方法的任何类和主应用程序位于同一台计算机上。这适用于任何解决方案。