栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

android NDK 如何使用 JNI 与 Java&Kotlin 语言交互?

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

android NDK 如何使用 JNI 与 Java&Kotlin 语言交互?

android NDK 如何使用 JNI 与 Java&Kotlin 语言交互?
主要三种情况

  1. 自带 JNIEnv 上下文,例如这种参数声明 extern "C" JNIEXPORT void JNICALLn ame(JNIEnv *env, jobject thiz){}
  2. 主线程反射调用 java/kotlin
  3. 其他线程反射调用 java/kotlin

情况 1 直接使用即可。
情况 2 通过 android Global JavaVM 获取当前 JNIEnv,例如使用函数 jint GetEnv(JavaVM *vm, void **env, jint version);。
情况3 通过 android Global JavaVM 获取当前 JNIEnv,例如使用函数 jint AttachCurrentThread(JavaVM *vm, void **p_env, void *thr_args); jint DetachCurrentThread(JavaVM *vm);;值得注意的是,线程中需要使用全局引用对象来获取类id。这可以在情况1中使用 jobject NewGlobalRef(JNIEnv *env, jobject obj); 函数获取一个全局引用对象。

引用类型在其他线程调用时,需要使用 jobject NewGlobalRef(JNIEnv *env, jobject obj); 函数获取一个全局引用,然后在其他线程使用这个全局引用即可。

class _jobject {};
class _jclass : public _jobject {};
class _jstring : public _jobject {};
class _jarray : public _jobject {};
class _jobjectArray : public _jarray {};
class _jbooleanArray : public _jarray {};
class _jbyteArray : public _jarray {};
class _jcharArray : public _jarray {};
class _jshortArray : public _jarray {};
class _jintArray : public _jarray {};
class _jlongArray : public _jarray {};
class _jfloatArray : public _jarray {};
class _jdoubleArray : public _jarray {};
class _jthrowable : public _jobject {};

具体代码如下所示(中间略有省略非必要代码,不过核心代码基本都在,基本流程已经过测试,可正常在主线程和非主线程与 java/kotlin语言交互):

#include 
#include 

#include 
#include 
#include 

// https://docs.oracle.com/javase/8/docs/api/overview-summary.html
// https://docs.oracle.com/en/java/javase/12/docs/specs/jni/index.html
// https://developer.android.com/ndk

// external fun name(); // kotlin
// native void name(); // Java

struct Context{
    JavaVM *vm;
    std::map dict;
} GlobalContext;

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *unused) {
    GlobalContext.vm = vm;
    JNIEnv *env;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        __android_log_print(ANDROID_LOG_VERBOSE, "main:", "VM address %p env %pn",vm,env);
        return JNI_ERR;
    }
    return JNI_VERSION_1_6;
}

// 主线程调用 java/kotlin 静态方法
// kotlin
//          @Keep
//          @JvmStatic
void call_java_static_function(JavaVM *vm) {
    JNIEnv *env;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        __android_log_print(ANDROID_LOG_VERBOSE, "main:", "JVM address %p env %pn",vm,env);
    }

    // env->FindClass()
    // env->GetMethodID()
    // env->CallStaticVoidMethod()
}

class Task {
public:
    Task(Context *ctx){
        this->ctx = ctx;
    }
    void operator()() {
        // other thread
        JNIEnv *env;
        if(ctx->vm->AttachCurrentThread(&env, NULL) != JNI_OK){
            __android_log_print(ANDROID_LOG_VERBOSE, "main:","Not AttachCurrentThread JNIEnvn");
            return;
        }

        // NewGlobalRef
        // DeleteGlobalRef
        auto obj = ctx->dict.at("install");
        // env->GetObjectClass(obj)
        // env->GetMethodID()
        // env->CallStaticVoidMethod()

        ctx->vm->DetachCurrentThread();
    }

private:
    Context *ctx;
};

// 其他线程调用 java/kotlin 静态方法
// kotlin
//          @Keep
//          @JvmStatic
void call_java_static_function_of_other_thread(Context *ctx) {
    std::thread run((Task(ctx)));
    run.detach();
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/934921.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号