繁体   English   中英

如何用JNI实例化共享指针调用java实现

[英]How to instantiate shared pointer with JNI to call java implementation

我是 JNI 和 C++ 的新手。我必须使用共享指针调用 lib function。 我的代码:

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>>中并将long作为jlong 返回。

注意事项:

  • 此代码保留全局引用以防止 Java 处理程序 object 被垃圾收集。
  • 当处理程序被销毁时,全局引用被释放。 如果您想释放 Java object,请确保在某个时候注销回调。
  • 我们使用 JNI Invocation API 中的 GetEnv 方法。如果当前 (C++) 线程已经附加到 JVM,它只会产生有用的值。如果失败,则需要调用vm->AttachCurrentThreadvm->AttachCurrentThreadAsDaemon .

暂无
暂无

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

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