美文网首页
Android NDK - JNI

Android NDK - JNI

作者: Lucky胡 | 来源:发表于2019-11-19 16:28 被阅读0次

    JNI基础知识

    数据类型

    JNI系统类型:JNIEnv(线程上下文)
    基本数据类型:int/float/long等等
    引用类型:String、Object、Class
    数组

    数据类型映射

    数据类型映射关系

    数组类型映射


    数组类型映射

    基本数据类型使用

    extern "C" JNIEXPORT jlong JNICALL
    Java_com_google_android_filament_RenderableManager_nCreateBuilder(JNIEnv*, jclass,
            jint count) {
        //基本数据类型可以直接使用
        int c_count = count;
        return (jlong) new RenderableManager::Builder((size_t) count);
    }
    

    实际上,这些基本数据类型,在C里面就是C的基本数据类型做了重命名。

    /* Primitive types that match up with Java equivalents. */
    typedef uint8_t  jboolean; /* unsigned 8 bits */
    typedef int8_t   jbyte;    /* signed 8 bits */
    typedef uint16_t jchar;    /* unsigned 16 bits */
    typedef int16_t  jshort;   /* signed 16 bits */
    typedef int32_t  jint;     /* signed 32 bits */
    typedef int64_t  jlong;    /* signed 64 bits */
    typedef float    jfloat;   /* 32-bit IEEE 754 */
    typedef double   jdouble;  /* 64-bit IEEE 754 */
    
    /* "cardinal indices and sizes" */
    typedef jint     jsize;
    
    
    typedef signed char __int8_t;
    typedef unsigned char __uint8_t;
    typedef short __int16_t;
    typedef unsigned short __uint16_t;
    typedef int __int32_t;
    typedef unsigned int __uint32_t;
    

    jstring的使用

    实际上,jstring就是个jobject

    typedef _jstring*       jstring;
    class _jstring : public _jobject {};
    

    jstring转换为C可以用的字符

    extern "C"
    JNIEXPORT void JNICALL
    Java_com_google_android_filament_RenderableManager_setName(JNIEnv *env, jclass clazz,
                                                               jstring name) {
        //C++方式
        //jstring -> char[]
        const char* charStr = env->GetStringUTFChars(name,NULL);
        printf(charStr);
        //使用完需要释放
        env->ReleaseStringUTFChars(name,charStr);
    
        //char[] -> jstring
        jstring str = env->NewStringUTF(charStr);
    
        //unicode编码的char
        const jchar* unicodeC = env->GetStringChars(name,NULL);
    }
    

    自动生成JNI的头文件

    在Java层写类,里面有native的方法。build项目。
    然后在build/intermediates/javac/debug/classes文件夹里,会生成所有的java类的.class文件。
    用javah命令,可以将.class生成.h文件。

    javah com.google.android.filament.Message
    

    Message.java

    package com.google.android.filament;
    
    /**
     * Created by junhu on 2019-11-19
     * 用于在JNI调用
     */
    public class Message {
        //签名:I
        public int what;
        //签名:Ljava/lang/Object
        public Object obj;
    
        //方法签名
        // "obtain","()Landroid/os/Message;"
        public static Message obtain(){return new Message();}
    
        //方法签名
        //"obtain","(Landroid/os/Handler;I)Landroid/os/Message;"
        public static Message obtain(float h,int what){return new Message();}
    
        //构造函数签名
        //"<init>","()V"
        public Message(){}
    
        public native void nativeEncry();
    }
    
    

    生成的.h如下:
    com_google_android_filament_Message.h

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_google_android_filament_Message */
    
    #ifndef _Included_com_google_android_filament_Message
    #define _Included_com_google_android_filament_Message
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_google_android_filament_Message
     * Method:    nativeEncry
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_com_google_android_filament_Message_nativeEncry
      (JNIEnv *, jobject);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    
    

    jobject的使用

    对象创建
    字段读写:实例字段、静态字段
    方法调用:实例方法、静态方法

    方法签名

    参数+返回值
    (Ljava/lang/String;)V
    代表参数为String,返回值为void

    (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;
    代表参数为(String,Object),返回值为String

    
    /**
     *
     * Class : Java_com_google_android_filament_RenderableManager_setName
     * Method : setName
     * Signature : (Ljava/lang/String;)V
     */
    JNIEXPORT void JNICALL Java_com_google_android_filament_RenderableManager_setName(JNIEnv *env, jclass clazz,
                                                               jstring name){}
    
    /**
     *
     * Class : Java_com_google_android_filament_RenderableManager_getName
     * Method : getName
     * Signature : (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;
     */
    JNIEXPORT jstring JNICALL Java_com_google_android_filament_RenderableManager_getName(JNIEnv *env, jclass clazz, jstring name,
                                                               jobject obj) {
    
    }
    
    JNI内部描述
    
    /**
     * Created by junhu on 2019-11-19
     * 用于在JNI调用
     */
    public class Message {
        //签名:I
        public int what;
        //签名:Ljava/lang/Object
        public Object obj;
    
        //方法签名
        // "obtain","()Landroid/os/Message;"
        public static Message obtain(){return new Message();}
    
        //方法签名
        //"obtain","(Landroid/os/Handler;I)Landroid/os/Message;"
        public static Message obtain(Handler h,int what){return new Message();}
    
        //构造函数签名
        //"<init>","()V"
        public Message(){}
    }
    
    

    获取实例字段

    实例字段

    获取静态字段

    静态字段

    实例

    JNIEXPORT void JNICALL
    Java_com_google_android_filament_RenderableManager_setMessage(JNIEnv *env, jclass clazz,
                                                                  jobject message) {
        //获取java的类
        jclass cls = env->GetObjectClass(message);
        //获取该值的field
        jfieldID field = env->GetFieldID(cls,"what","I");
        //设置值
        env->SetIntField(message,field,-1);
        //获取值
        jint what = env->GetIntField(message,field);
    }
    

    方法调用

    实例方法


    方法调用

    静态方法


    静态方法调用
        //获取java类
        jclass cls = env->FindClass("android/os/Message");
        //获取静态方法id
        jmethodID methodId = env->GetStaticMethodID(cls,"obtain","()Landroid/os/Message;");
        //调用静态方法
        jobject message = env->CallStaticObjectMethod(cls,methodId);
    

    创建对象

    创建对象
        //获取java类
        jclass  clz = env->FindClass("android/os/Message");
        //获取构造方法
        jmethodID constructor = env->GetMethodID(clz,"<init>","()V");
        jobject message = env->NewObject(clz,constructor);
    

    数组操作

        jsize size = env->GetArrayLength(messages);
        for (int i = 0; i < size; ++i) {
            //获取到array里的单个实例
            jobject message = env->GetObjectArrayElement(messages,i);
            
        }
    

    相关文章

      网友评论

          本文标题:Android NDK - JNI

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