Java类型和本地类型对应

在如下情况下,需要在本地方法中应用java对象的引用,就会用到类型之间的转换:

  1. java方法里面将参数传入本地方法;
  2. 在本地方法里面创建java对象;
  3. 在本地方法里面return结果给java程序。

Java基本类型

像booleans、integers、floats等从Java程序中传到本地方法中的原始类型可以直接使用,下面是java中的原始类型和本地方法中的类型的对应:

Java 类型本地类型说明

boolean jboolean 无符号,8 位
byte jbyte 无符号,8 位
char jchar 无符号,16 位
short jshort 有符号,16 位
int jint 有符号,32 位
long jlong 有符号,64 位
float jfloat 32 位
double jdouble 64 位
void void N/A  

也就是说如果我在方法中传进去了一个boolean的参数的话,那么我在本地方法中就有jboolean类型与之对应。同理,如果在本地方法中return一个jint的话,那么在java中就返回一个int类型。

为了使用方便,特提供以下定义。

#define JNI_FALSE 0
#define JNI_TRUE 1

jsize 整数类型用于描述主要指数和大小:
typedef jint jsize;

Java String类型

在java中,使用的字符串String对象是Unicode码,即每个字符不论是中文还是英文或是符号,一个字符总是占用两个字节。
在c/c++本地代码中创建java的String对象
.java通过JNI接口可以将java的字符串转换到c/c++中的宽字符串(wchar_t ),或是传回一个UTF-8的字符串(char )到c/c++。反过来,c/c++可以通过一个宽字符串,或是一个UTF-8编码的字符串来创建一个java端的String对象。

GetStringChars/GetStringUTFChars

.这两个函数用来取得与某个jstring对象相关的java字符串。分别可以取得UTF-16编码的宽字符串(jchar)跟UTF-8编码的字符串(char)。

Const jchar* GetStringChars(jstring str, jboolean* copied)
Const char* GetStringUTFChars(jstring str, jboolean* copied)

第一个参数传入一个指向java中的String对象的jstring变量
第二个参数传入的是一个jboolean的指针。
这两个函数分别都会有两个不同的动作:
第一个参数:

  1. 开新内存,然后把java中的String拷贝到这个内存中,然后返回这个内存地址的指针。
  2. 直接返回指向java中string的内存的指针,这个时候千万不要改变这个内存的内容,这将破坏String在java中始终是常量这个原则。
    第二个参数:
    是用来标示是否对java的string对象进行了拷贝的。
    如果传入的这个jboolean指针不是null,则他会给该指针指向的内存传入JNI_TRUE或JNI_FALSE标示是否进行了拷贝。
    传入null标示不关心是否拷贝字符串,它就不会给jboolean*指向的内存赋值。
    使用这两个函数取得的字符串,在不使用的时候,要使用ReleaseStringChars/ReleaseStringUTFChars来释放拷贝的内存,或是释放对java的String对象的引用。

    ReleaseStringChars(jstring jstr, const jchar* str);
    ReleaseStringUTFChars(jstring jstr, const char* str);

第一个参数指定一个jstring变量,即是要释放的本地字符串的来源。
第二个参数就是要释放的本地字符串

访问类对象的属性

env 为 JNIEnv,obj的类型为jobject

JAVA_FieldAccessTest_accessField(JNIEnv *env,jobject obj){jfieldID fid;jclass cls = (*env)->GetObjectClass(env, obj);//类FieldAccessTest中有个String类型的属性s//获取要访问的属性的idfid = (*env)->GetFieldID(evn,cls,"s","Ljava/lang/String;");//读取属性值jstring jstr = (*env)->GetObjectField(env,obj,fid);char* str  = (*evn)->GetStringUTFChars(env,jstr,NULL);//释放资源
(*env)->ReleaseStringUTFChars(env,jstr,str);//现在反过来,改变调用该本地方法的java对象的属性值jstr = (*env)->NewStringUTF(env,"88888");(*env)->SetObjectField(env,obj,fid,jstr);}

总结:

1. jfieldID fid = (*env)->GetFieldID(env,对象所属的类的jclass,属性名,属性对应的属性描述符号);
2. (*env)->GetObjectField(env,对象,属性id);

访问静态属性:

假如有个类如下:

class StaticFielcTest {private static int si;private native void accessField();
}

那么实现为:

JNIEXPORT void JNICALL
Java_StaticFieldTest_accessField(JNIEnv *env, jobject obj)
{jfieldID fid;   /* store the field ID */jint si;jclass cls = (*env)->GetObjectClass(env, obj);   //获取类classfid = (*env)->GetStaticFieldID(env, cls, "si", "I");  //获取静态属性idsi = (*env)->GetStaticIntField(env, cls, fid);   //读去属性的值(*env)->SetStaticIntField(env, cls, fid, 200);  //设置静态属性的值
}

访问实例方法

假如有个这样的类:

class MethodCall {private native void nativeMethod();private void callback() {System.out.println("In Java CallBack");}public static void main(String args[]) {MethodCall c = new MethodCall();c.nativeMethod();
} static {System.loadLibrary("InstanceMethodCall");}
}

jni实现:

JNIEXPORT void JNICALL
Java_MethodCall_nativeMethod(JNIEnv *env, jobject obj)
{//1.拿到classjclass cls = (*env)->GetObjectClass(env, obj);                         //2.拿到方法idjmethodID mid = (*env)->GetMethodID(env, cls, "callback", "()V");           //3.根据obj,和方法id 调用方法(*env)->CallVoidMethod(env, obj, mid);
}

根据方法的返回值来决定调用哪个方法:

如果返回int 那么最后一步就调用 (*env)->CallIntMethod(env,obj,mid);

最后那个参数 "()V" 是方法描述符:

(I)V 带一个int 类型的参数,返回值类型为void
()D 没有参数,返回double //注意!!没有参数并不是 (V)D

方法public static void main(String[] args) 对应的方法描的符为:

([Ljava/lang/String;)V

访问静态方法

jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mid =(*env)->GetStaticMethodID(env, cls, "callback", "()V");
(*env)->CallStaticVoidMethod(env, cls, mid);    //注意,这里跟访问实例方法的区别是 第二个参数不是obj,而是cls

转载于:https://www.cnblogs.com/CommonQ/p/4062392.html

Android JNI和NDK学习(5)--JNI分析API相关推荐

  1. ndk学习20: jni之OnLoad动态注册函数

    一.原理 当在系统中调用System.loadLibrary函数时,该函数会找到对应的动态库, 然后首先试图找到"JNI_OnLoad"函数,如果该函数存在,则调用它 JNI_On ...

  2. Android studio 使用NDK工具实现JNI编程

    前言: Android开发中常常会使用到第三方的.so库.在使用.so库的时候就要用到JNI编程.JNI是Java Native Interface的缩写.它提供了若干的API实现了Java和其它语言 ...

  3. Android NDK学习:JNI中的数组、引用和异常的处理

    JNI的文档 https://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html JNI数组操作 调用数组 Java ...

  4. JNI与NDK学习第二篇-----应用篇

    2019独角兽企业重金招聘Python工程师标准>>> 1.安装配置NDK 1). 解压NDK的zip包到非中文目录(最好英文目录不要带空格)     2). 配置path : 解压 ...

  5. NDK学习笔记-JNI的引用

    JNI中的引用意在告知虚拟机何时回收一个JNI变量 JNI引用变量分为局部引用和全局引用 局部引用 局部引用,通过DeletLocalRef手动释放对象 原因 访问一个很大的Java对象,使用之后还用 ...

  6. Android:JNI与NDK(四) Shell脚本的学习以及交叉编译libjpeg图片处理库

    本篇目录 一.前言 首先,向关注公众号的朋友们道个歉,很长时间没更新了,实在惭愧,这段时间忙于个人事务,耽误了很长时间. 各位小伙伴们可以关注一下我的个人github地址:https://github ...

  7. NDK学习笔记:JNI调用Java层方法创建Native的AudioTrack播放PCM(方法签名,CallXXXMethod)

    NDK学习笔记:JNI调用Java层方法创建Native的AudioTrack播放PCM 题目有点复杂,不过确实就是那么回事.这章想记录的内容比较多,先列出来: native static 与 nat ...

  8. 【Android NDK 开发】JNI 动态注册 ( 动态注册流程 | JNI_OnLoad 方法 | JNINativeMethod 结构体 | GetEnv | RegisterNatives )

    文章目录 I . 动态注册流程 ( 总结 ) II . JNI_OnLoad 方法 III . 被注册的本地 C/C++ 方法参数 IV . JNINativeMethod 结构体 ( 核心重点 ) ...

  9. Android JNI学习(四)——JNI的常用方法的API

    前三篇主要讲解了jni基础相关的理论知识,今天主要讲解一下JNI的常用方法的API,掌握了基本的理论知识和常用的API接下来才能更好的实战. jni的常用API大纲 再看API前,我建议大家主要结合官 ...

最新文章

  1. 秒杀系统怎么设计?8张图带你搞定!
  2. jQuery元素过滤
  3. jquery对json的各种遍历
  4. python贪心算法求删数问题_贪心算法删数问题
  5. python中的不可变对象_python中的可变与不可变对象
  6. 23种设计模式(十三)接口隔离之门面模式
  7. OpenCV(一)---支持向量机 SVM
  8. 最小二乘法正规方程推导过程
  9. 微信小程序项目实践 项目范围及开发计划
  10. win10系统如何设置局域网服务器,win10系统如何设置局域网共享
  11. 人类无法抗拒的十大心理学效应
  12. 开启功放安桥TX-NR515的ARC(音频回传通道)功能
  13. Python selenium 模拟登录QQ空间
  14. 独立分包中包含app.wxss的问题
  15. 2017清北学堂(提高组精英班)集训笔记——基础算法
  16. 什么是soft matting方法_宜家的娃娃为什么这么”丑“
  17. 基于Matlab计算经典CFAR阈值
  18. 如何选择适合你的兴趣爱好(六十),电子琴
  19. Scala 连接Redis工具类
  20. Django框架(八)--单表增删改查,在Python脚本中调用Django环境

热门文章

  1. [pytorch、学习] - 9.1 图像增广
  2. HTML学习笔记06-连接
  3. Spring 框架的JDBC模板技术
  4. Ubuntu14.04下Mongodb数据库可视化工具安装部署步骤(图文详解)(博主推荐)
  5. C语言错误: HEAP CORRUPTION DETECTED
  6. Android L 的 Tint(着色)
  7. SQL Server Insert 操作效率(堆表 VS 聚集索引表)
  8. 新浪微博2-找到用户的accessToken
  9. 巧妙的有css合并图片解决tab切换的背景图片
  10. 《C#3.0 in a Nutshell,3rd Edition》之C#3.0和.net3.5基本介绍篇