美文网首页
JNI调用java自定义类

JNI调用java自定义类

作者: 隔壁家de老王 | 来源:发表于2021-07-16 11:25 被阅读0次

    一,注册java方法和jni方法相对应

     static const JNINativeMethod gMethods[] = {
            //name   //signature   //funcPtr
            {"testObjectJNI","(Lcom/zero/sdk/jnitest/TestMsg;)I",(void *)jni_test},
    };
    
    
    JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved){
        JNIEnv* env = NULL;
        if(vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) //从JavaVM获取JNIEnv,一般使用1.4的版本
            return -1;
        jclass clazz = env->FindClass(JAVA_CLASS_PATH);
        if (!clazz){
            LOGW("cannot get class");
            return -1;
        }
        if(env->RegisterNatives(clazz, gMethods, sizeof(gMethods)/sizeof(gMethods[0])))
        {
            LOGW("register native method failed!");
            return -1;
        }
        return JNI_VERSION_1_4;
    }
    

    二,通过接口传递java类
    java定义接口

     private native int testObjectJNI(TestMsg responseMsg)
    

    c++定义接口

    static jint jni_test(JNIEnv* pEnv, jobject , jobject arg)
    {}
    

    三,java层创建对象传递并通过native接口传递到c++层

    TestMsg testMsg = new TestMsg();
    testMsg.msg = "server is hungry!";
    testMsg.subTestMsg = new TestMsg.SubTestMsg();
    testObjectJNI(testMsg); //调用native通信接口
    System.out.println("=================code:"+testMsg.code+";msg:"+ testMsg.msg+";subMsg:"+testMsg.subTestMsg.subMsg);
    

    四,c++层获取java类以及其成员数据并修改设置

    const char* buf  = "code is success";
    const char* subBuf  = "sub code is success";
    
    static jint jni_test(JNIEnv* pEnv, jobject , jobject arg)
    {
        jclass jcarg =GetClassOrDie(pEnv,arg);
        jfieldID iid = GetFieldIDOrDie(pEnv,jcarg, "code", "I");
        pEnv->SetIntField(arg,iid,200);
        jfieldID strid = GetFieldIDOrDie(pEnv,jcarg, "msg", "Ljava/lang/String;");
    
        SetChar2JString(pEnv,arg,strid,buf);
    
        jfieldID subMsgId = GetFieldIDOrDie(pEnv,jcarg,"subTestMsg","Lcom/zero/sdk/jnitest/TestMsg$SubTestMsg;");
        if (!subMsgId){
            LOGW("===========================subMsgId is null");
        }
        jobject subObj = pEnv->GetObjectField(arg, subMsgId);
    
        if (!subObj){
            LOGW("===========================subObj is null");
        }
    
        jclass subClass = FindClassOrDie(pEnv,"com/zero/sdk/jnitest/TestMsg$SubTestMsg");
        if (!subClass) {
            LOGW("===========================findClass is null");
        }
        jfieldID subStrid = GetFieldIDOrDie(pEnv,subClass,"subMsg", "Ljava/lang/String;");
        if (!subStrid){
            LOGW("===========================subStrid is null");
        }
    
        SetChar2JString(pEnv,subObj,subStrid,subBuf);
    
        return 0;
    }
    
    

    附完整实现code:
    c++实现接口

    #include <jni.h>
    #include <string>
    #include <android/log.h>
    #include "core_jni_helpers.h"
    
    
    #define TAG "SceneManager" // 这个是自定义的LOG的标识
    #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型
    #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型
    #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义LOGW类型
    #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型
    #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定义LOGF类型
    
    
    
    extern "C" JNIEXPORT jstring JNICALL
    Java_com_zero_sdk_jnitest_MainActivity_stringFromJNI(
            JNIEnv *env,
            jobject obj) {
        std::string hello = "Hello from C++";
        jstring jstr = env->NewStringUTF(hello.c_str());
        return jstr;
    }
    
    const char* SCENE_REMOTE_PROXY_PATH = "com/zero/sdk/jnitest/MainActivity";
    const char* buf  = "code is success";
    const char* subBuf  = "sub code is success";
    
    static jint jni_test(JNIEnv* pEnv, jobject , jobject arg)
    {
        jclass jcarg =GetClassOrDie(pEnv,arg);
        jfieldID iid = GetFieldIDOrDie(pEnv,jcarg, "code", "I");
        pEnv->SetIntField(arg,iid,200);
        jfieldID strid = GetFieldIDOrDie(pEnv,jcarg, "msg", "Ljava/lang/String;");
    
        SetChar2JString(pEnv,arg,strid,buf);
    
        jfieldID subMsgId = GetFieldIDOrDie(pEnv,jcarg,"subTestMsg","Lcom/zero/sdk/jnitest/TestMsg$SubTestMsg;");
        if (!subMsgId){
            LOGW("===========================subMsgId is null");
        }
        jobject subObj = pEnv->GetObjectField(arg, subMsgId);
    
        if (!subObj){
            LOGW("===========================subObj is null");
        }
    
        jclass subClass = FindClassOrDie(pEnv,"com/zero/sdk/jnitest/TestMsg$SubTestMsg");
        if (!subClass) {
            LOGW("===========================findClass is null");
        }
        jfieldID subStrid = GetFieldIDOrDie(pEnv,subClass,"subMsg", "Ljava/lang/String;");
        if (!subStrid){
            LOGW("===========================subStrid is null");
        }
    
        SetChar2JString(pEnv,subObj,subStrid,subBuf);
    
        return 0;
    }
    
    
    static const JNINativeMethod gMethods[] = {
            //name   //signature   //funcPtr
            {"testObjectJNI","(Lcom/zero/sdk/jnitest/TestMsg;)I",(void *)jni_test},
    };
    
    
    JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved){
        JNIEnv* env = NULL;
        if(vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) //从JavaVM获取JNIEnv,一般使用1.4的版本
            return -1;
        jclass clazz = env->FindClass(SCENE_REMOTE_PROXY_PATH);
        if (!clazz){
            LOGW("cannot get class SceneRemoteProxy");
            return -1;
        }
        if(env->RegisterNatives(clazz, gMethods, sizeof(gMethods)/sizeof(gMethods[0])))
        {
            LOGW("register native method failed!");
            return -1;
        }
        return JNI_VERSION_1_4;
    }
    

    java调用

    
        // Used to load the 'native-lib' library on application startup.
        static {
            System.loadLibrary("native-lib");
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // Example of a call to a native method
            TextView tv = findViewById(R.id.sample_text);
            TestMsg testMsg = new TestMsg();
            testMsg.msg = "server is hungry!";
            testMsg.subTestMsg = new TestMsg.SubTestMsg();
            // ResponseMsg resMsg = returnRespose();
            testObjectJNI(testMsg);
            System.out.println("=================code:"+testMsg.code+";msg:"+ testMsg.msg+";subMsg:"+testMsg.subTestMsg.subMsg);
        }
    
        /**
         * A native method that is implemented by the 'native-lib' native library,
         * which is packaged with this application.
         */
        public native String stringFromJNI();
    
        private native int testObjectJNI(TestMsg responseMsg);
    
    

    java数据结构

    package com.zero.sdk.jnitest;
    
    public class TestMsg {
        public String msg;
        public int code;
        public SubTestMsg subTestMsg;
        public static class SubTestMsg{
            public String subMsg;
        }
    }
    

    jni 方法封装类

    /*
     * Copyright (C) 2014 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    #ifndef CORE_JNI_HELPERS
    #define CORE_JNI_HELPERS
    
    // Defines some helpful functions.
    
    #ifdef NDEBUG
    #define REG_JNI(name)      { name }
        struct RegJNIRec {
            int (*mProc)(JNIEnv*);
        };
    #else
    #define REG_JNI(name)      { name, #name }
    struct RegJNIRec {
        int (*mProc)(JNIEnv*);
        const char* mName;
    };
    #endif
    
    static inline jclass FindClassOrDie(JNIEnv* env, const char* class_name) {
        jclass clazz = env->FindClass(class_name);
        return clazz;
    }
    
    static inline jclass GetClassOrDie(JNIEnv* env, jobject arg) {
        jclass jcarg = env->GetObjectClass(arg);
        return jcarg;
    }
    
    static inline jfieldID GetFieldIDOrDie(JNIEnv* env, jclass clazz, const char* field_name,
                                           const char* field_signature) {
        jfieldID res = env->GetFieldID(clazz, field_name, field_signature);
        return res;
    }
    
    static inline jmethodID GetMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name,
                                             const char* method_signature) {
        jmethodID res = env->GetMethodID(clazz, method_name, method_signature);
        return res;
    }
    
    static inline jfieldID GetStaticFieldIDOrDie(JNIEnv* env, jclass clazz, const char* field_name,
                                                 const char* field_signature) {
        jfieldID res = env->GetStaticFieldID(clazz, field_name, field_signature);
        return res;
    }
    
    static inline jmethodID GetStaticMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name,
                                                   const char* method_signature) {
        jmethodID res = env->GetStaticMethodID(clazz, method_name, method_signature);
        return res;
    }
    
    static inline void SetChar2JString(JNIEnv* env,jobject obj,jfieldID id, const char* value) {
        jstring strBuf = env->NewStringUTF(value);
        env->SetObjectField(obj, id, strBuf);
    }
    
    template <typename T>
    static inline T MakeGlobalRefOrDie(JNIEnv* env, T in) {
        jobject res = env->NewGlobalRef(in);
        return static_cast<T>(res);
    }
    
    
    
    
    #endif  // CORE_JNI_HELPERS
    
    

    相关文章

      网友评论

          本文标题:JNI调用java自定义类

          本文链接:https://www.haomeiwen.com/subject/qjovpltx.html