如何使用 JNI 实例化共享指针来调用 java 实现
How to instantiate shared pointer with JNI to call java implementation
我是 JNI 和 C++ 的新手。我必须用共享指针调用 lib 函数。我的代码:
JNIEXPORT jint JNICALL Java_com_test_NativeClient_subscribe(JNIEnv* env, jobject thisObj, jobject handler) {
jclass handlerClass = env->GetObjectClass(handler);
jmethodID starts = env->GetMethodID(handlerClass, "starts", "(I)V");
jmethodID joins = env->GetMethodID(handlerClass, "joins", "(Ljava/lang/String;Ljava/lang/String;)V");
// int subscribe(std::shared_ptr< SomeHandler > handler) // I need implement this
std::shared_ptr<?> sharedPointer = new std::shared_ptr<?>;
return some::lib::subscribe(sharedPointer);
}
SomeHandler 它是来自 lib - some::lib::SomeHamdler 的接口,但我也在方法(作业对象处理程序)中传递了 java 实现。如何在执行订阅方法后正确定义 sharedPointer 以调用 java 实现?提前致谢。
UPD:Java代码:
public native int subscribe(SomeHandler handler); // native method in NativeClient
SomeHandler 接口:
public interface SomeHandler {
void starts(int uptime);
void joins(String mac, String name);
SomeHandlerImpl class:
public class SomeHandlerImpl implements SomeHandler {
@Override
public void starts(int uptime) {
System.out.println("uptime is " + uptime);
}
@Override
public void joins(String mac, String name) {
System.out.println("mac: " + mac + ", nName: " + name);
}
您需要做的就是存储对 jobject
的全局引用并编写一些包装代码:
class JavaWrapperHandler : public some::lib::callback {
jobject java_handler;
public:
JavaWrapperHandler(jobject handler) {
JNIEnv *env = nullptr;
vm->GetEnv(&env, JNI_VERSION_1_6);
java_handler = env->NewGlobalRef(handler);
}
~JavaWrapperHandler() {
JNIEnv *env = nullptr;
vm->GetEnv(&env, JNI_VERSION_1_6);
env->DeleteGlobalRef(java_handler);
}
virtual joins(std::string mac, std::string name) {
JNIEnv *env = nullptr;
vm->GetEnv(&env, JNI_VERSION_1_6);
jclass handlerClass = env->GetObjectClass(java_handler);
jmethodID joins = env->GetMethodID(handlerClass, "joins", "(Ljava/lang/String;Ljava/lang/String;)V");
env->CallVoidMethod(java_handler, joins, ...);
};
};
您可以在 JNI 方法中按如下方式实例化它:
std::make_shared<JavaWrapperHandler>(handler);
请注意,您仍然需要在某个地方再次存储 shared_ptr
,否则它会立即被释放。例如,您可以将其存储在 std::map<long, shared_ptr<JavaWrapperHandler>>
和 return 和 long
中作为 jlong
.
注意事项:
- 此代码保留全局引用以防止 Java 处理程序对象被垃圾收集。
- 销毁处理程序时释放全局引用。如果您想释放 Java 对象,请确保在某个时候注销回调。
- 我们使用 JNI 调用中的 GetEnv 方法 API。如果当前 (C++) 线程已经附加到 JVM,它只会产生有用的值。如果失败,需要调用
vm->AttachCurrentThread
或vm->AttachCurrentThreadAsDaemon
.
我是 JNI 和 C++ 的新手。我必须用共享指针调用 lib 函数。我的代码:
JNIEXPORT jint JNICALL Java_com_test_NativeClient_subscribe(JNIEnv* env, jobject thisObj, jobject handler) {
jclass handlerClass = env->GetObjectClass(handler);
jmethodID starts = env->GetMethodID(handlerClass, "starts", "(I)V");
jmethodID joins = env->GetMethodID(handlerClass, "joins", "(Ljava/lang/String;Ljava/lang/String;)V");
// int subscribe(std::shared_ptr< SomeHandler > handler) // I need implement this
std::shared_ptr<?> sharedPointer = new std::shared_ptr<?>;
return some::lib::subscribe(sharedPointer);
}
SomeHandler 它是来自 lib - some::lib::SomeHamdler 的接口,但我也在方法(作业对象处理程序)中传递了 java 实现。如何在执行订阅方法后正确定义 sharedPointer 以调用 java 实现?提前致谢。
UPD:Java代码:
public native int subscribe(SomeHandler handler); // native method in NativeClient
SomeHandler 接口:
public interface SomeHandler {
void starts(int uptime);
void joins(String mac, String name);
SomeHandlerImpl class:
public class SomeHandlerImpl implements SomeHandler {
@Override
public void starts(int uptime) {
System.out.println("uptime is " + uptime);
}
@Override
public void joins(String mac, String name) {
System.out.println("mac: " + mac + ", nName: " + name);
}
您需要做的就是存储对 jobject
的全局引用并编写一些包装代码:
class JavaWrapperHandler : public some::lib::callback {
jobject java_handler;
public:
JavaWrapperHandler(jobject handler) {
JNIEnv *env = nullptr;
vm->GetEnv(&env, JNI_VERSION_1_6);
java_handler = env->NewGlobalRef(handler);
}
~JavaWrapperHandler() {
JNIEnv *env = nullptr;
vm->GetEnv(&env, JNI_VERSION_1_6);
env->DeleteGlobalRef(java_handler);
}
virtual joins(std::string mac, std::string name) {
JNIEnv *env = nullptr;
vm->GetEnv(&env, JNI_VERSION_1_6);
jclass handlerClass = env->GetObjectClass(java_handler);
jmethodID joins = env->GetMethodID(handlerClass, "joins", "(Ljava/lang/String;Ljava/lang/String;)V");
env->CallVoidMethod(java_handler, joins, ...);
};
};
您可以在 JNI 方法中按如下方式实例化它:
std::make_shared<JavaWrapperHandler>(handler);
请注意,您仍然需要在某个地方再次存储 shared_ptr
,否则它会立即被释放。例如,您可以将其存储在 std::map<long, shared_ptr<JavaWrapperHandler>>
和 return 和 long
中作为 jlong
.
注意事项:
- 此代码保留全局引用以防止 Java 处理程序对象被垃圾收集。
- 销毁处理程序时释放全局引用。如果您想释放 Java 对象,请确保在某个时候注销回调。
- 我们使用 JNI 调用中的 GetEnv 方法 API。如果当前 (C++) 线程已经附加到 JVM,它只会产生有用的值。如果失败,需要调用
vm->AttachCurrentThread
或vm->AttachCurrentThreadAsDaemon
.