美文网首页
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