android jni 调用java对象_Android NDK开发之Jni调用Java对象

本地代码中使用Java对象

通过使用合适的JNI函数,你可以创建Java对象,get、set 静态(static)和 实例(instance)的域,调用静态(static)和实例(instance)函数。JNI通过ID识别域和方法,一个域或方法的ID是任何处理域和方法的函数的必须参数。

下表列出了用以得到静态(static)和实例(instance)的域与方法的JNI函数。每个函数接受(作为参数)域或方法的类,它们的名称,符号和它们对应返回的jfieldID或jmethodID。

函数

描述

GetFieldID

得到一个实例的域的ID

GetStaticFieldID

得到一个静态的域的ID

GetMethodID

得到一个实例的方法的ID

GetStaticMethodID

得到一个静态方法的ID

构造一个Java对象的实例

C代码  822f4ede0250764c15072b281c444b2e.png

jclass cls = (*env)->FindClass(env, "Lpackagename/classname;");  //创建一个class的引用

jmethodID id = (*env)->GetMethodID(env, cls, "", "(D)V");  //注意这里方法的名称是"",它表示这是一个构造函数,而且构造参数是double型的

jobject obj = (*env)->NewObjectA(env, cls, id, args);  //获得一实例,args是构造函数的参数,它是一个jvalue*类型。

首先是获得一个Java类的class引用 (*env)->FindClass(env, "Lpackagename/classname;");  请注意参数:Lpackagename/classname;,L代表这是在描述一个对象类型,packagename/classname是该对象耳朵class路径,请注意一定要以分号(;)结束!

然后是获取函数的id,jmethodID id = env->GetMethodID(cls, "", "(D)V");  第一个是刚刚获得的class引用,第二个是方法的名称,最后一个就是方法的签名了

还是不懂?我曾经如此,请接着看...

难理解的函数签名

JNINativeMethod的定义如下:

typedef struct{const char*name;const char*signature;void*fnPtr;

} JNINativeMethod;

第一个变量name是Java中函数的名字。

第二个变量signature,用字符串是描述了函数的参数和返回值

第三个变量fnPtr是函数指针,指向C函数。

其中比较难以理解的是第二个参数,例如

"()V"

"(II)V"

"(Ljava/lang/String;Ljava/lang/String;)V"

实际上这些字符是与函数的参数类型一一对应的。

"()" 中的字符表示参数,后面的则代表返回值。例如"()V" 就表示void Func();

"(II)V" 表示 void Func(int, int);

那其他情况呢?请查看下表:

类型

符号

boolean

Z

byte

B

char

C

short

S

int

I

long

L

float

F

double

D

void

V

object对象

LClassName;      L类名;

Arrays

[array-type        [数组类型

methods方法

(argument-types)return-type     (参数类型)返回类型

稍稍补充一下:

1、方法参数或者返回值为java中的对象时,签名中必须以“L”加上其路径,不过此路径必须以“/”分开,自定义的对象也使用本规则

比如说 java.lang.String为“java/lang/String”,com.nedu.jni.helloword.Student为"Lcom /nedu/jni/helloword/Student;"

2、方法参数或者返回值为数组类型时,请前加上[

例如[I表示 int[],[[[D表示 double[][][],即几维数组就加几个[

d8b39960f04576ee0d79529f4adfcb2f.png

在本地方法中调用Java对象的方法

1、获取你需要访问的Java对象的类:

jclass cls = (*env)->GetObjectClass(env, obj); //使用GetObjectClass方法获取obj对应的jclass。

jclass cls = (*env)->FindClass(“android/util/log”) //直接搜索类名,需要是static修饰的类。

2、获取MethodID:

jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V"); //GetStaticMethodID(…),获取静态方法的ID使用GetMethdoID方法获取你要使用的方法的MethdoID

使用CallVoidMethod方法调用方法。参数的意义:

env-->JNIEnv

obj-->通过本地方法穿过来的jobject

mid-->要调用的MethodID(即第二步获得的MethodID)

depth-->方法需要的参数(对应方法的需求,添加相应的参数)

注:这里使用的是CallVoidMethod方法调用,因为没有返回值,如果有返回值的话使用对应的方法,在后面会提到。

CallVoidMethod CallStaticVoidMethod

CallIntMethod CallStaticVoidMethod

CallBooleanMethod CallStaticVoidMethod

CallByteMethod CallStaticVoidMethod

现在稍稍明白文章开始构造Java对象那个实例了吧?让我们继续深入一下:

Jni操作Java的String对象

从java程序中传过去的String对象在本地方法中对应的是jstring类型,jstring类型和c中的char*不同,所以如果你直接当做char*使用的话,就会出错。因此在使用之前需要将jstring转换成为c/c++中的char*,这里使用JNIEnv提供的方法转换。

const char *str = (*env)->GetStringUTFChars(env, jstr, 0);

(*env)->ReleaseStringUTFChars(env, jstr, str);

这里使用GetStringUTFChars方法将传进来的prompt(jstring类型)转换成为UTF-8的格式,就能够在本地方法中使用了。

注意:在使用完你所转换之后的对象之后,需要显示调用ReleaseStringUTFChars方法,让JVM释放转换成UTF-8的string的对象的空间,如果不显示的调用的话,JVM中会一直保存该对象,不会被垃圾回收器回收,因此就会导致内存溢出。

下面是Jni访问String对象的一些方法:

GetStringUTFChars          将jstring转换成为UTF-8格式的char*

GetStringChars               将jstring转换成为Unicode格式的char*

ReleaseStringUTFChars    释放指向UTF-8格式的char*的指针

ReleaseStringChars         释放指向Unicode格式的char*的指针

NewStringUTF               创建一个UTF-8格式的String对象

NewString                    创建一个Unicode格式的String对象

GetStringUTFLength      获取UTF-8格式的char*的长度

GetStringLength           获取Unicode格式的char*的长度

下面提供两个String对象和char*互转的方法:

/* c/c++ string turn to java jstring */

jstring charToJstring(JNIEnv* env, const char* pat)

{

jclass strClass = (*env)->FindClass(env, "java/lang/String");

jmethodID ctorID = (*env)->GetMethodID(env, strClass, "", "([BLjava/lang/String;)V");

jbyteArray bytes = (*env)->NewByteArray(env, strlen(pat));

(*env)->SetByteArrayRegion(env, bytes, 0, strlen(pat), (jbyte*)pat);

jstring encoding = (*env)->NewStringUTF(env, "UTF-8");

return (jstring)(*env)->NewObject(env, strClass, ctorID, bytes, encoding);

}

/* java jstring turn to c/c++ char* */

char* jstringToChar(JNIEnv* env, jstring jstr)

{

char* pStr = NULL;

jclass jstrObj = (*env)->FindClass(env, "java/lang/String");

jstring encode = (*env)->NewStringUTF(env, "utf-8");

jmethodID methodId = (*env)->GetMethodID(env, jstrObj, "getBytes", "(Ljava/lang/String;)[B");

jbyteArray byteArray = (jbyteArray)(*env)->CallObjectMethod(env, jstr, methodId, encode);

jsize strLen = (*env)->GetArrayLength(env, byteArray);

jbyte *jBuf = (*env)->GetByteArrayElements(env, byteArray, JNI_FALSE);

if (jBuf > 0)

{

pStr = (char*)malloc(strLen + 1);

if (!pStr)

{

return NULL;

}

memcpy(pStr, jBuf, strLen);

pStr[strLen] = 0;

}

env->ReleaseByteArrayElements(byteArray, jBuf, 0);

return pStr;

}

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

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

相关文章

docker 容器端口访问不到_docker容器无法访问宿主机端口的解决

最近在工作时遇到一个问题,docker容器无法访问宿主机的redis,telent6379端口不通。 经排查发现,该服务器启用了防火墙,防火墙把6379的端口的访问授权给docker0网卡访问即可。 操作如下: firewall-cmd --permanent --zone=trusted --change-interface=docker0 firewall-cmd…

java class isassignablefrom_Java之——Class的isAssignableFrom方法

转载请注明出处 https://blog.csdn.net/l1028386804/article/details/80508540Class的isAssignableFrom方法定义如下public native boolean isAssignableFrom(Class ? cls);由方法签名可见是一个本地方法 即C代码编写的。以下是JDK中的注释Determines if the class or interfa…

java中堆栈的基本操作_玩儿转队列和栈的基本操作及其应用:Java 版

队列的基本操作队列入队出队实现队列是种先进先出的数据结构。队列的基本操作主要是入队和出队。数据从队尾进入队列,从队首出队列。下面来写一个简单的队列:public class MyQueue {private List data;private int pointer;public MyQueue() {data new ArrayList&l…

java界面编辑教程_java程序设计基础教程第六章图形用户界面编辑.docx

java程序设计基础教程第六章图形用户界面编辑.docx还剩27页未读,继续阅读下载文档到电脑,马上远离加班熬夜!亲,很抱歉,此页已超出免费预览范围啦!如果喜欢就下载吧,价低环保!内容要点…

c盘java文件误删_java获取C盘下的隐藏目录文件名称

题记—— 执剑天涯,从你的点滴积累开始,所及之处,必精益求精,即是折腾每一天。网易云课堂在Java中, File类用来将文件或者文件夹封装成对象,方便对文件与文件夹的属性信息进行操作。File对象可以作为参数传…

对java这门课程的认识_关于java课程的总结

前言本次博客主要内容为此次三次作业的总结,整门java课程学习的总结,以及在此次java课程中的收获,和对课程的意见。作业过程总结第一次作业主要考察的是对程序的可扩展性,实现开闭原则非常重要,因为程序随着时间&#…

linux php和java环境变量配置_Linux下配置Java环境变量

一般来说,我们都会把Java安装到 /usr/local 目录 或者 /opt 目录下。这里假设java安装包已解压在了 /opt下,具体目录为:/opt/java8/java1.8.0_45目录(注意:如果是生产环境中,一定要root用户来安装配置)。下面我们来配置…

java多线程多态_Java学习之多线程

多线程:(一)进程与线程进程特点并发与并行的区别:多线程编程的好处:(二)多线程的建立1,通过继承Thread类,代码如下:class MyThread extendsThread {private static int K 10;//类共享变量private int M10;…

php seaslog安装,浅谈win10下安装php seaslog扩展的方法

本篇文章给大家分享一下win10 php安装seaslog扩展的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。【推荐学习:《PHP视频教程》】一、检查系统环境情况使用phpinfo()检查系统环境情况,找到需要下载的配置…

php里push的用法,php array_push函数怎么用?

php array_push函数用于向数组尾部插入一个或多个元素,其语法是array_push(array,value1,value2...),参数array必需,指规定一个数组;value1必需,指规定要添加的值。php array_push函数怎么用?定义和用法arr…

java if (name!=null name!=),java中的NullPointerException异常

java中的NullPointerException异常关注:176 答案:3 mip版解决时间 2021-01-27 20:59提问者侢遇噹姩揂2021-01-27 02:10Login.jsp提供登录表单。到LoginCheck.jsp发生空指针异常错误。LoginCheck.jsp:String userName request.getParameter("userName");String pas…

caany边缘检测matlab,自适应canny算法研究及其在图像边缘检测中的应用.pdf

自适应canny算法研究及其在图像边缘检测中的应用.pdf还剩51页未读,继续阅读下载文档到电脑,马上远离加班熬夜!亲,很抱歉,此页已超出免费预览范围啦!如果喜欢就下载吧,价低环保!内容要…

flask mysql orm,flask的orm框架(Flask-SQLAlchemy)-创建表

标签:# 转载请留言联系ORM 是什么?ORM,Object-Relation Mapping。意思就是对象-关系映射。ORM 主要实现模型对象到关系数据库数据的映射。优点 :只需要面向对象编程, 不需要面向数据库编写代码.对数据库的操作都转化成对类属性和方法的操作.不…

php+使用go编译,golang如何编译

Go语言中使用 go build 命令主要用于编译代码。在包的编译过程中,若有必要,会同时编译与之相关联的包。go build 有很多种编译方法,如无参数编译、文件列表编译、指定包编译等,使用这些方法都可以输出可执行文件。go build 无参数…

oracle19c监听服务启动失败,Oracle19c安装(有失败成功记录)

Oracle19c安装(有失败成功记录)失败过程失败安装设置 (图为安装成功后获取)成功过程安装设置配置监听桌面类与服务器类的区别总结说明:失败过程失败问题一模一样,无论安装成功或者失败都出现“无法添加用户XXXX到%2%组中”的弹窗,都是点6下继…

linux ospf 命令,OSPF单区域配置 - linuxprobe2020的个人空间 - OSCHINA - 中文开源技术交流社区...

为了弥补距离矢量路由协议的不足,IEFI组织开发了一种基于链路状态的内部网关协议OSPF实验环境:红,绿,蓝三个颜色区域代表三个不同网络的办公场所,要求使用OSPF协议实现网络互通。pc1:172.16.1.1pc2:172.16.2.1pc3:172.…

ubuntu下的linux怎样备份文件,Ubuntu系统如何备份还原?Ubuntu系统备份还原教程

Ubuntu系统如何备份还原?Ubuntu系统是一个以桌面应用为主的开源操作系统,专为开发团队而打造!无论你使用的是什么操作系统,都有可能出现电脑无法修复的故障,这时候备份还原功能就显得非常重要了。今天小编要给大家分享…

jenkins linux编译c,【Linux】【Jenkins】代码编译和执行过程中的问题汇总

1.问题1:java.io.FileNotFoundException: /root/.jenkins/workspace/Videoyi_AutoTest_Maven/config-log4j\log4j.xml (No such file or directory)该问题是由于代码是在windows下编写和编译的,使用的都是\\来实现目录结构的,结果到linux下的…

linux清理整个磁盘空间,一次Linux磁盘空间清理的经历

最近,在Linux上运行BPM应用总是报没有空间的错误。经过一番调查和周折,终于找出了问题的症结,并顺利解决。今天,我把过程总结一下,方便自己或其他有类似问题的朋友参考。这里不对具体命令的具体各种参数做深入介绍&…

c语言手游常用代码,c语言源代码【操作流程】

很多小伙伴都遇到过c语言源代码的困惑吧,一些朋友看过网上零散的c语言源代码的处理方法,并没有完完全全明白c语言源代码是如何解决的,今天小编准备了简单的解决办法,只需要按照1:编写C源代码for_learning_compile.c2&a…