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);
}
网友评论