JNI - C++/Java 中的侦听器 - 是不是可以在 C++ 中实例化 Java 对象并将它们用作参数
Posted
技术标签:
【中文标题】JNI - C++/Java 中的侦听器 - 是不是可以在 C++ 中实例化 Java 对象并将它们用作参数【英文标题】:JNI - Listener in C++/Java - is it possible to instantiate Java objects in c++ and use them as parametersJNI - C++/Java 中的侦听器 - 是否可以在 C++ 中实例化 Java 对象并将它们用作参数 【发布时间】:2014-03-27 10:27:14 【问题描述】:以下内容是否可用于 JNI?
public NativeClass
static
System.loadLibrary("dll");
public static native void addListener(Listener listener);
public interface Listener
public void eventOccurred(Info info);
public Info
private final String s1;
private final String s2;
public Info(String s1, String s2);
// ... getters for use in Java
可以吗
在 dll 上注册一个Listener
对象(据我发现应该没问题)
在c/c++代码中实例化一个Info
对象,作为调用Listener.eventOccured(Info...)
的参数?
或者什么是实现从 DLL 获取一些信息的侦听器的好方法?
在我的情况下 - 我们有一个 dll 可以做一些工作。我们从java调用这个dll。现在我们想为 dll 附加一个监听器,以便在工作时向我们推送一些进度信息。上面的例子是监听部分,不知道c/c++的构造函数调用Java构造函数是否可行。
在哪里可以找到描述答案的文档的提示会很好 - 我找不到回答我的问题的信息。
一小段代码,描述 c/c++ 部分将是锦上添花:)
【问题讨论】:
【参考方案1】:简短的回答是肯定的,您可以通过 JNI 在本机层中保存、实例化和传递 Java 对象。
在 jni 文档中,您会找到可以为您执行此操作的函数。 http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html
您还将使用javap -s
和javah
来帮助查找用于jni 的Java 方法签名并制作您的jni 标头。见http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javap.html & http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javah.html
以下是您将要执行的操作的示例。我没有测试过它,所以只是将它用作编写自己的参考。注意:注意包符号(我假设没有包)和例外。任何 JNI 调用(env->...
)都可能发生异常,因此请查看有关如何处理异常的文档(ExceptionCheck
、ExceptionDescribe
、ExceptionClear
)。
JavaVM * savedVM = NULL;
JNIEXPORT void JNICALL Java_NativeClass_addListener(JNIEnv *env, jobject obj_instance, jobject listener_instance)
env->GetJavaVM( &savedVM );
//save listener_instance for use later
saved_listener_instance = listener_instance;
void doSomething()
//Get current thread JNIEnv
JNIEnv * ENV;
int stat = savedVM->GetEnv((void **)&ENV, JNI_VERSION_1_6);
if (stat == JNI_EDETACHED) //We are on a different thread, attach
savedVM->AttachCurrentThread((void **) &ENV, NULL);
if( ENV == NULL )
return; //Cant attach to java, bail
//Get the Listener class reference
jclass listenerClassRef = ENV->GetObjectClass( saved_listener_instance );
//Use Listener class reference to load the eventOccurred method
jmethodID listenerEventOccured = ENV->GetMethodID( listenerClassRef, "eventOccurred", "(LInfo;)V" );
//Get Info class reference
jclass infoClsRef = ENV->FindClass( "Info" );
//Create Info class
jobject info_instance = ENV->NewObject( infoClsRef, ..... );//For you to fill in with your arguments
//invoke listener eventOccurred
ENV->CallVoidMethod( saved_listener_instance, listenerEventOccured, info_instance );
//Cleanup
ENV->DeleteLocalRef( info_instance );
【讨论】:
太好了,我找不到,或者是盲目地找到带有 ENV->NewObject(...) 的部分,以确保可以做我想做的事情。感谢您的完整回答!【参考方案2】:这是一个很好的例子:https://github.com/NickZt/MyJNACallbackTest 此处详细解释了相同的代码: https://www.hackster.io/user2657268124/a-beginner-s-guide-to-implement-jni-callbacks-in-android-cd8226
【讨论】:
以上是关于JNI - C++/Java 中的侦听器 - 是不是可以在 C++ 中实例化 Java 对象并将它们用作参数的主要内容,如果未能解决你的问题,请参考以下文章
Java Native Interface (JNI) 是不是受 C++ ABI 兼容性问题的影响?
使用 JNI 在 C 中访问 Java 对象中的 Java 对象
从本机 c 代码 (JNI) 为 Java 中的回调函数传递多个参数