内构函数java_Android JNI参数传递
Java中调用native函数传递的参数是Java数据类型,到了JNI层需进行数据类型转换,基本数据类型是在前面加个j,如int——>jint,应用数据类型除了基本数据类型的数据、Class、String和Throwable外,其余所有Java对象的数据类型在JNI中都用jobject表示。
//Java层com.xxx.yyy包MyJni.java中的jnitest有三个参数
jnitest(String path, String name, MyJni mj);
//JNI层对应的函数的后三个参数与jnitest的参数对应
com_xxx_yyy_MyJni_jnitest(JNIEnv *env, jobject thiz, jstring path, jstring name, jobject mj);
若对象类型都用就object表示,就好比是native层的void* 类型一样。第二个参数就object代表Java层的实例对象,如果Java层是static函数,则这个参数将是jclass,表示在调用哪个Java Class的静态函数。
JNIEnv介绍
JNIEnv是一个与线程相关的代表JNI环境的结构体,内部结构如图:
从上图可知JNIEnv提供了一些JNI系统函数:
调用Java的函数
操作jobejct对象等很多事情
每个线程都有一个JNIEnv,由于线程相关,所以一个线程不能使用另一个线程的JNIEnv结构体。JNIEnv是native函数转换成JNI层函数后有虚拟机传进来的,但当后台线程收到一个网络消息,且需有native层函数主动回调Java层函数时,JNIEnv如何传递?
这就要用到JavaVM,它是虚拟机在JNI层的代表,如下:
//全进程只有一个JavaVM对象,可保存且在任何地方都可使用
jint JNI_OnLoad(JavaVM* vm, void* reserved);
而JavaVM 和 JNIEnv的关系如下:
调用JavaVM的AttachCurrentThread函数,就可得到这个线程的JNIEnv结构体,即可在后台回调Java函数。
在后台线程退出前,需调用JavaVM的DetachCurrentThread函数释放对应的资源。
通过JNIEnv操作jobject
Java引用类型除了少数几个外,其余在JNI层都会用jobject来表示对象的数据类型,操作jobject的本质是操作Java对象的成员变量和成员函数。
jfieldID 和 jmethodID 介绍
JNI规则中用jfieldID 和 jmethodID表示Java类的成员变量和成员函数,可通过JNIEnv的函数得到:
jfieldID GetFieldID(jclass clazz, const char *name, const char *sig);
jmethodID GetMethodID(jclass clazz, const char *name, const char *sig);
其中,jclass表示Java类,name表示成员函数或成员变量的名字,sig为这个函数和变量的签名信息。使用方法如下:
MyJni(JNIEnv *env, jobject mj)......
{
//先找到com.xxx.yyy.MyJni类在JNI层中对应的jclass实例。
jclass myJniInterface = env->FindClass("com.xxx.yyy.MyJni");
//取出MyJni类中函数jnitest的jMethodID。
mMyJniMethodID = env->GetMethodID(myJniInterface, "jnitest", "(Ljava/lang/String;JJ)V");
//取出MyJni类中函数jnitest1的jMethodID。
mJniTestMethodID = env->GetMethodID(myJniInterface, "jnitest1",
"(Ljava/lang/String;Ljava/lang/String;)V");
如果每次操作jobject前都去查询jmethodID或jfieldID,将会影响程序的运行效率,故在初始化时可取出ID并保存起来供后续使用。
使用jfieldID 和 jmethodID
实例代码如下:
virtual bool myjni(const char* path, long long lastModified, long long fileSize)
{
jstring pathstr;
if ((pathStr = mEnv->NewStringUTF(path)) == NULL)
return;
/*
调用JNIEnv的CallVoidMethod函数,注意CallVoidMethod的参数:
第一个是MyJni的jobject对象,
第二个是函数myjni的jmethodID,后面是Java中myjni的参数
*/
mEnv->CallVoidMethod(mClient, mMyJniMethodID, pathStr, lastModified, fileSize);
mEnv->DeleteLocalRef(pathStr);
return (!mEnv->ExceptionCheck());
通过JNIEnv输出CallVoidMethod,再把jobject、jMethodID和对应的参数传进去,JNI层就能调用Java对象的函数。
实际上JNIEnv输出一系列类似CallVoidMethod的函数,形式如下:
NativeType CallMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
其中type对应Java函数的返回值类型,例如CallIntMethod、CallVoidMethod等。
上面是针对非static函数,如果调用Java的static函数,则用JNIEnv输出的CallStatic< Type>Method系列函数。
通过jfieldID操作jobject的成员变量,如下:
//获得filedID可调用GetField系列函数获取jobject对应的成员变量值
nativeType GetField(JNIEnv *env, jobject obj, jfieldID fieldID)
//或调用SetField系列函数设置jobject对应的成员变量值
void SetField(JNIEnv *env, jobject obj, jfield fieldID, NativeType value)
JNI类型签名介绍
static JNINativeMethod gMethods[] = {
......
{
"processFile"
"(Ljava/lang/String;Ljava/lang/String;Landroid/media/MyJni;)V",
(void*)com_xxx_yyy_MyJni
},
......
}
代码中字符串”(Ljava/lang/String;Ljava/lang/String;Landroid/media/MyJni;)V”是Java中对应函数的签名信息,有参数类型和返回值类型共同组成。Java支持函数重载,可定义同名但不同参数的函数,进根据函数名无法找到具体函数,故JNI技术中将参数类型和返回值类型作为函数的签名信息。
JNI规范定义的函数签名信息格式:
(参数1类型标示参数2类型标示...参数n类型标示)返回值类型标示
“(Ljava/lang/String;Ljava/lang/String;Landroid/media/MyJni;)V”,其中括号内是参数类型的标识,最右边是返回值类型的标识,void类型对应的标识是V。当参数的类型是引用类型时,其格式是“L包名;”,其中包名中的“.”换成“/”。Ljava/lang/String表示是一个Java的String类型。
内构函数java_Android JNI参数传递相关推荐
- Python函数细节:多数量参数、强制参数传递、返回多值、匿名/内联函数
1. 可接受任意数量参数的函数 接受任意数量的位置参数,使用参数*来解决 # rest是由所有其他位置参数组成的元组 def avg(first, *rest):return ( first + su ...
- python3 内置函数
""" # 内置函数之---abs():绝对值 # a = 10086 a = 'hello' try:print(abs(a))with open('666.p', ' ...
- Python基础11-函数式编程与内置函数
目录 函数即变量 lambda关键字定义匿名函数 高阶函数 内置函数map 内置函数filter 内置函数reduce 内置函数看文档 函数即变量 书接上回,Python里面,函数就是变量,可以被当成 ...
- python常用的内置函数
内置函数,就是Python提供的, 可以直接拿来直接用的函数. 一.数字相关 01 数据类型 bool() 描述:测试一个对象是True, 还是False.bool 是 int 的子类. 语法:cla ...
- day4 匿名函数、装饰器、生成器、迭代器、内置函数、 json 与 pickle 模块
文章目录 1.列表生成式 2.匿名函数 3.装饰器 4.生成器 5.迭代器 6.内置函数 7.json & pickle 序列化与反序列化 1.列表生成式 可通过特定语句便捷生成列表 list ...
- c语言函数参数类型检查,内联函数在编译时是否做参数类型检查?
先说宏和函数的区别: 1. 宏做的是简单的字符串替换(注意是字符串的替换,不是其他类型参数的替换),而函数的参数的传递,参数是有数据类型的,可以是各种各样的类型. 2. 宏的参数替换是不经计算而直接处 ...
- 列举5个python内置函数_Python5个内建高阶函数的使用
描述 本文结合各种实际的例子详细讲解了Python5个内建高阶函数的使用,能够帮助理解Python的数据结构和提高数据处理的效率,这5个函数分别是: map reduce filter sorted/ ...
- 深浅拷贝、函数、内置函数、文件处理、三元运算、递归
深浅拷贝 import copy copy.copy() #浅拷贝 copy.deepcopy() #深拷贝 num = 110 copynum = num #赋值 一.数字和字符串 对于 数字 和 ...
- python常用内置函数总结-Python 常用内置函数
Python 常用内置函数如下: 1. abs()函数返回数字的绝对值. print( abs(-45) )# 返回45print("abs(0.2):",abs(0.2))#返回 ...
最新文章
- 对称加密----AES和DES加密、解密
- python视频下载-Python实现视频下载功能
- jquery判断页面滚动条(scroll)是上滚还是下滚,且是否滚动到头部或者底部
- C#中教你一步步实现一个电话本窗体程序
- 大棚骨架搭建好 科学施肥增收增产
- rssi室内定位算法原理_室内定位方案常用的4种定位算法
- php正则表达式 包含特殊字符,php正则表达式的特殊字符含义
- mac文件丢失,苹果电脑有没有好用的恢复软件?
- 清华紫光输入法linux,紫光拼音输入法
- FLASH闪存编程原理与步骤
- 如何更改Excel2016中折线图的连接点颜色和样式?
- 8脚语音芯片指的是什么?有什么特点?以及如何区分和选型
- 给深度学习新手做项目的10个建议
- 100 Most Brilliant Tech Hacks You Need To Know Right Now
- 知乎热榜“人脸安全”,这些博主怎么看
- 跟着老猫来搞GO-基础进阶
- docker 批量垃圾清理
- 2021年挖矿电脑配置推荐
- Qt_OpenCV_VS2013配置方法
- 量化投资实战教程(1)—基于backtrader的简单买入卖出策略
热门文章
- html怎么在字体中加波浪线,CSS3实现文字波浪线效果
- linux隐藏apache信息,Linux下如何隐藏Apache版本号信息
- CSS3 线性渐变背景的过渡效果
- UE4 HTC VIVE - 番外篇 - 局域网联机(一)
- 深入浅出FSUIPC的作用以及使用方法
- 简单的UTF8编码生成
- 设计模式C++实现 ——状态模式
- C++设计模式之三 单例模式
- centos 6 安装mysql,CentOS6.5安装MySQL教程(完整教程)
- SharePoint List item数量超过5000的解决办法