Android JNI和NDK学习(5)--JNI分析API

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/273536.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMq 消费失败,重试机制

方案一: 本地消息表 定时任务 本地消息表:主要用于存储 业务数据、交换机、队列、路由、次数 定时任务:定时扫描本地消息表,重新给业务队列投递消息。 具体思路:业务队列消费失败时,把 业务数据、交换机、…

Android常用的工具类

主要介绍总结的Android开发中常用的工具类,大部分同样适用于Java。目前包括HttpUtils、DownloadManagerPro、ShellUtils、PackageUtils、 PreferencesUtils、JSONUtils、FileUtils、ResourceUtils、StringUtils、 ParcelUtils、RandomUtils、ArrayUtils、ImageUtils…

0. Spring 基础

BeanDefinition BeanDefinition 表示 Bean 定义: Spring根据BeanDefinition来创建Bean对象;BeanDefinition有很多的属性用来描述Bean;BeanDefiniton是Spring中非常核心的概念。BeanDefiniton中重要的属性: a. beanClass&#xf…

1. Spring 源码:Spring 解析XML 配置文件,获得 Bena 的定义信息

通过 Debug 运行 XmlBeanDefinitionReaderTests 类的 withFreshInputStream() 的方法&#xff0c;调试 Spring 解析 XML 配置文件&#xff0c;获得 Bean 的定义。 大体流程可根据序号查看&#xff0c;xml 配置文件随便看一眼&#xff0c;不用过多在意。 <?xml version&qu…

c++ 读取文件 最后一行读取了两次

用ifstream的eof()&#xff0c;竟然读到文件最后了&#xff0c;判断eof还为false。网上查找资料后&#xff0c;终于解决这个问题。 参照文件&#xff1a;http://tuhao.blogbus.com/logs/21306687.html 在使用C/C读文件的时候&#xff0c;一定都使用过eof&#xff08;&#xff0…

java中的io系统详解(转)

Java 流在处理上分为字符流和字节流。字符流处理的单元为 2 个字节的 Unicode 字符&#xff0c;分别操作字符、字符数组或字符串&#xff0c;而字节流处理单元为 1 个字节&#xff0c;操作字节和字节数组。 Java 内用 Unicode 编码存储字符&#xff0c;字符流处理类负责将外部的…

js获取字符串最后一个字符代码

方法一&#xff1a;运用String对象下的charAt方法 charAt() 方法可返回指定位置的字符。 代码如下 复制代码 str.charAt(str.length – 1) 请注意&#xff0c;JavaScript 并没有一种有别于字符串类型的字符数据类型&#xff0c;所以返回的字符是长度为 1 的字符串 方法二&#…

Unity3D Shader入门指南(二)

关于本系列 这是Unity3D Shader入门指南系列的第二篇&#xff0c;本系列面向的对象是新接触Shader开发的Unity3D使用者&#xff0c;因为我本身自己也是Shader初学者&#xff0c;因此可能会存在错误或者疏漏&#xff0c;如果您在Shader开发上有所心得&#xff0c;很欢迎并恳请您…

JVM:如何分析线程堆栈

英文原文&#xff1a;JVM: How to analyze Thread Dump 在这篇文章里我将教会你如何分析JVM的线程堆栈以及如何从堆栈信息中找出问题的根因。在我看来线程堆栈分析技术是Java EE产品支持工程师所必须掌握的一门技术。在线程堆栈中存储的信息&#xff0c;通常远超出你的想象&…

一个工科研究生毕业后的职业规划

http://blog.csdn.net/wojiushiwo987/article/details/8592359一个工科研究生毕业后的职业规划 [wojiushiwo987个人感触]:说的很诚恳&#xff0c;对于马上面临毕业的我很受用&#xff0c;很有启发。有了好的职业生涯规划&#xff0c;才有了前进的方向和动力&#xff0c;才能…

SQLSERVER中如何忽略索引提示

SQLSERVER中如何忽略索引提示 原文:SQLSERVER中如何忽略索引提示SQLSERVER中如何忽略索引提示 当我们想让某条查询语句利用某个索引的时候&#xff0c;我们一般会在查询语句里加索引提示&#xff0c;就像这样 SELECT id,name from TB with (index(IX_xttrace_bal)) where bal…

JavaScript——以简单的方式理解闭包

闭包&#xff0c;在一开始接触JavaScript的时候就听说过。首先明确一点&#xff0c;它理解起来确实不复杂&#xff0c;而且它也非常好用。那我们去理解闭包之前&#xff0c;要有什么基础呢&#xff1f;我个人认为最重要的便是作用域&#xff08;lexical scope&#xff09;&…

jquery实现二级联动不与数据库交互

<select id"pro" name"pro" style"width:90px;"></select> <select id"city" name"city" style"width: 90px"></select> $._cityInfo [{"n":"北京市","c"…

[016]转--C++拷贝构造函数详解

一. 什么是拷贝构造函数 首先对于普通类型的对象来说&#xff0c;它们之间的复制是很简单的&#xff0c;例如&#xff1a; [c-sharp] view plaincopy int a 100; int b a; 而类对象与普通对象不同&#xff0c;类对象内部结构一般较为复杂&#xff0c;存在各种成员变量。下…

js中调用C标签实现百度地图

<script type"text/javascript"> //json数组 var jsonArray document.getElementById("restaurant").value; var map new BMap.Map("milkMap"); // 创建地图实例 <c:forEach items"${restaurantlist}" var"…

jquery较验组织机构编码

//*************************组织机构码较验************************* function checkOrganizationCode() { var weight [3, 7, 9, 10, 5, 8, 4, 2]; var str 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ; var reg /^([0-9A-Z]){8}-[0-9|X]{1}$/; var organizationcode $("…

自定义GrildView实现单选功能

首先看实现功能截图&#xff0c;这是一个自定义Dialog,并且里面内容由GrildView 绑定数据源&#xff0c;实现类似单选功能。 首先自定义Dialog&#xff0c;绑定数据源 自定义Dialog弹出框大小方法 最主要实现的就是点击颜色切换的功能&#xff0c;默认GrildView的每一项都是蓝色…

Java数字字符串如何转化为数字数组

eg&#xff1a; String numberString "0123456789"; 如何转化为&#xff1a;int[] digitArry new int[]{0,1,2,3,4,5,6,7,8,9}; 解决办法&#xff1a; char[] digitNumberArray numberString.toCharArray(); int[] digitArry new int[digitString.toCharArray().l…

『重构--改善既有代码的设计』读书笔记----序

作为C的程序员&#xff0c;我从大学就开始不间断的看书&#xff0c;看到如今上班&#xff0c;也始终坚持每天多多少少阅读技术文章&#xff0c;书看的很多&#xff0c;但很难有一本书&#xff0c;能让我去反复的翻阅。但唯独『重构--改善既有代码的设计』这本书让我重复看了不下…

微信公共平台接口开发--Java实现

Java微信实现&#xff0c;采用SpringMVC 架构&#xff0c;采用SAXReader解析XML RequestMapping(value"/extend") public class WeixinController { RequestMapping(value"/weixin") public ModelAndView weixin(HttpServletRequest request,HttpServlet…