如何使用 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->AttachCurrentThreadvm->AttachCurrentThreadAsDaemon.