关于jni中默认方法参数的解释

包含jni的项目中,一般都创建一个native方法,这个方法的创建会影响在使用javah编译成的.h文件例如:

我在MainActivity中创建了native方法,传递一个int数组:

那么会在.h文件中出现对应的内容:

JNIEXPORT void JNICALL Java_com_array_MainActivity_changeArray
  (JNIEnv * env, jobject obj, jintArray jarrays);

三个参数JNIEnv *, jobject, jintArray含义:

参数1:在jni.h文件中,可以发现有这样的一行:(我的是在149行,可以Ctrl+f查找JNIEnv)

struct _JNIEnv;
这里声明了一个结构 为tJNIEnv;

在这里又声明了一个类型:

typedef _JNIEnv JNIEnv;
这时我们就明白了,第一个参数可以帮我们拿到一个指针,通过该指针可以找到jni.h文件中的各种方法,方便java和C的交互。


参数2:obj代表执行此JNI操作的类实例引用,就是哪一个类调用了jni,obj就代表这个类实例化之后的引用。


参数3:你自己想传递的参数,以上是我传递了一个int类型的数组,当然你也可以传递其他数据,但是你需要注意java和C数据类型的转换,例如char C中为 1byte但在java中  为2byte,C没有String等等。


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
介绍当下多数在java下执行lua脚本的程序都是用了luajava。然而luajava存在一些严重的问题,它会将byte数组和string等同对待,而且它的反射执行效率比较低。为了弥补这些问题,我参考luajava,重写了它的java和jni代码,并以mLua为名重新发布。特点描述和luajava类似的,mLua也有内置的全局lua函数;java对象和lua对象可以通过jni层代码进行交换。但是mLua禁止lua直接操作java对象,如果想在lua使用java对象,必须使用内置的全局函数实现。mLua区分byte数组和string。在mLua,java的byte数组对lua端而言,只是一个普通的userdata。在跨语言数据交换的时候,string是被复制的,因此当一个string从lua传递到java后再于lua修改它,它在java端的对应版本并不会随着改变。将lua端的number传递给java后,会被优先解释为byte类型,否则将依照byte - short - int - long - float - double链条来尝试解释。mLua不对外暴露lua解析器实例,所有的操作都基于MLua实例完成。java端方法描述mLua的java端方法在MLua方法名称方法解释setBasedir(String)设置lua代码的最外层目录,所有lua代码都应该存放在这个目录或其子目录下pushGlobal(String, Object)设置全局lua的全局变量或函数,可以push普通的Object,或者JavaFunction。后者表示一个lua函数的java实现。只有在start方法执行前,设置的数据才会生效start(String)启动lua解析器,传递的参数表示lua代码的入口文件stop()停止lua解析器并释放资源除此之外,JavaFunction也是使用者可能需要用到的接口。它表示一个lua函数的java实现。其回调方法execute(Object[])方法会传入从lua端输入的数据,并输出一个结果传回lua端。如果方法本身不需要返回数据,则返回null即可。lua端函数描述在mLua下,lua原来的require、print函数已经被改写。requirerequire必须使用设置在java端的basedir为根目录的相对路径引用其他lua脚本:require "dir1/dir2/script1" require "script2"print支持输出一个或多个对象,但是不能将string与java对象作拼接:-- 正确的做法 -- print("hello mLua") print("context: ", getContext()) print("string " .. 111) -- 错误的做法 -- print("context: " .. getContext())通过逗号分隔的对象会在java端以tab号分隔显示操作java对象mLua也采用反射来操作java对象,不过mobTools的ReflectHelper具备缓存功能,理论上会比luajava每次直接反射更快。mLua提供了如下的内置函数:函数名称函数解释import(className)向ReflectHelper类缓存导入一个类,此函数将返回一个string,用于后续代码从缓存重新获取导入的类实例import(name, className)向ReflectHelper类缓存导入一个类,并将此缓存的key设置为指定名称new(className, ...)构造一个java实例,参数className是import函数的返回值,后续参数为java构造方法的输入参数invokeStatic(className, methodName, ...)调用一个java的静态方法invoke(receiver, methodName, ...)调用一个Java的实例方法getStatic(className, fieldName)获取一个java的静态字段setStatic(className, fieldName, value)设置一个java的静态字段get(receiver, fieldName)获取一个java的实例字段set(receiver, fieldName, value)设置一个java的实例字段createProxy(proxyTable, ...)构造一个java接口代理。参数proxyTable是一个lua的table,其的key必须与java接口类的方法名称相同,key对应的value是一个lua的function,function的参数列表和返回值也必须与java接口相同。proxyTable后的参数是被实现的接口列表名称,皆为string,由import函数返回。此函数将返回一个java接口代理实例,可将此实例传回java端并进行操作,当实例的接口函数被调用时,mLua会调用proxyTable的对应funtion代码完成操作例子java端代码public class MainActivity extends Activity {     private MLua lua;     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         // 构造一个解析器实例         lua = new MLua();         // 设置lua代码存放位置         lua.setBasedir("/sdcard/mLua/LuaTest");         // push全局对象         lua.pushGlobal("getContext", new JavaFunction() {             public Object execute(Object[] args) throws Throwable {                 return getApplication();             }         });         try {             // 启动解析器,设置main.lua为入口代码             lua.start("main");         } catch (Throwable e) {             e.printStackTrace();         }     }     protected void onDestroy() {         // 关闭解析器         lua.stop();         super.onDestroy();     } }lua端代码-- 导入ReflectHelper.ReflectRunnable类,并命名为ReflectRunnable -- import("ReflectRunnable", "com.mob.tools.utils.ReflectHelper$ReflectRunnable") local function main()   -- 演示print和invoke --   print("hello world from mLua")   local context = getContext()   print("current context: ", context)   local packageName = invoke(context, "getPackageName")   print("packageName: ", packageName)   -- 演示java接口代理 --   local luaCode = {     run = function(arg)       print("luaCode.run(), input: ", arg)       return "yoyoyo"     end   }   local proxy = createProxy(luaCode, "ReflectRunnable")   local res = invoke(proxy, "run", packageName)   print("luaCode.run(), output: ", res)   -- 演示数组复制 --   local bArray = new("[B", 16)   for i = 0, 15 do     set(bArray, "[" .. i .. "]", i   1)   end   local bArray2 = new("[B", get(bArray, "length"))   invokeStatic("System", "arraycopy", bArray, 0, bArray2, 0, 16)   for i = 0, 15 do     print("bArray2[" .. i .. "]: ", get(bArray2, "[" .. i .. "]"))   end end main()扩展mLua默认只能从文件系统加载lua代码,但是如果对MLua的setBasedir方法进行重写,以其他的方式实现SourceLoader,则可以加载任意方式的lua代码,包括assets的,和加密的。 标签:mLua
第1章 Android平台上的C++入门 1.1 Microsoft Windows 1.1.1 在Windows平台上下载并安装JDK开发包 1.1.2 在Windows平台上下载并安装ApacheANT 1.1.3 在Windows平台上下载并安装AndroidSDK 1.1.4 在Windows平台上下载并安装Cygwin 1.1.5 在Windows平台上下载并安装AndroidNDK 1.1.6 在Windows平台上下载并安装Eclipse 1.2 AppleMacOSX 1.2.1 在Mac平台上安装Xcode 1.2.2 验证Mac平台的Java开发包 1.2.3 验证Mac平台上的ApacheANT 1.2.4 验证GNUMake 1.2.5 在Mac平台上下载并安装AndroidSDK 1.2.6 在Mac平台上下载并安装AndroidNDK 1.2.7 在Mac平台上下载并安装Eclipse 1.3 UbuntuLinux 1.3.1 检查GNUC库版本 1.3.2 激活在64位系统上支持32位的功能 1.3.3 在Linux平台上下载并安装Java开发工具包(JDK) 1.3.4 在Linux平台上下载并安装ApacheANT 1.3.5 在Linux平台上下载并安装GNUMake 1.3.6 在Linux平台上下载并安装AndroidSDK 1.3.7 在Linux平台上下载并安装AndroidNDK 1.3.8 在Linux平台上下载并安装Eclipse 1.4 下载并安装ADT 1.4.1 安装Android平台包 1.4.2 配置模拟器 1.5 小结 第2章 深入了解AndroidNDK 2.1 AndroidNDK提供的组件 2.2 AndroidNDK的结构 2.3 以一个示例开始 2.3.1 指定AndroidNDK的位置 2.3.2 导入示例项目 2.3.3 向项目添加原生支持 2.3.4 运行项目 2.3.5 用命令行对项目进行构建 2.3.6 检测AndroidNDK项目的结构 2.4 构建系统 2.4.1 Android.mk 2.4.2 Application.mk 2.5 使用NDK-Build脚本 2.6 排除构建系统故障 2.7 小结 第3章 用JNI实现与原生代码通信 3.1 什么是JNI 3.2 以一个示例开始 3.2.1 原生方法的声明 3.2.2 加载共享库 3.2.3 实现原生方法 3.3 数据类型 3.3.1 基本数据类型 3.3.2 引用类型 3.4 对引用数据类型的操作 3.4.1 字符串操作 3.4.2 数组操作 3.4.3 NIO操作 3.4.4 访问域 3.4.5 调用方法 3.4.6 域和方法描述符 3.5 异常处理 3.5.1 捕获异常 3.5.2 抛出异常 3.6 局部和全局引用 3.6.1 局部引用 3.6.2 全局引用 3.6.3 弱全局引用 3.7 线程 3.7.1 同步 3.7.2 原生线程 3.8 小结 第4章 使用SWIG自动生成JNI代码 4.1 什么是SWIG 4.2 安装 4.2.1 Windows平台上SWIG的安装 4.2.2 在MacOSX下安装 4.2.3 在UbuntuLinux下安装 4.3 通过示例程序试用SWIG 4.3.1 接口文件 4.3.2 在命令行方式下调用SWIG 4.3.3 将SWIG集成到Android构建过程 4.3.4 更新Activity. 4.3.5 执行应用程序 4.3.6 剖析生成的代码 4.4 封装C语言代码 4.4.1 全局变量 4.4.2 常量 4.4.3 只读变量 4.4.4 枚举 4.4.5 结构体 4.4.6 指针 4.5 封装C++代码 4.5.1 指针、引用和值 4.5.2 默认参数 4.5.3 重载函数 4.5.4 类 4.6 异常处理 4.7 内存管理 4.8 从原生代码调用Java 4.8.1 异步通信 4.8.2 启用Directors 4.8.3 启用RTTI 4.8.4 重写回调方法 4.8.5 更新HeIIojniActivity 4.9 小结 第5章 日志、调试及故障处理 5.1 日志 5.1.1 框架 5.1.2 原生日志API 5.1.3 受控制的日志 5.1.4 控制台日志 5.2 调试 5.2.1 预备知识 5.2.2 调试会话建立 5.2.3 建立调试示例 …… 第6章 BionicAPI入门 第7章 原生线程 第8章 POSIXSocketAPI:面向连接的通信 第9章 POSIXSocketAPI:无连接的通信 第10章 POSIXSocketAPI:本地通信 第11章 支持C++ 第12章 原生图形API 第13章 原生音频API 第14章 程序概要分析和NEON优化
JDK 8的新功能 1.Java编程语言 Lambda Expressions是一种新的语言功能,已在此版本引入。它们使您可以将功能视为方法参数,或将代码视为数据。Lambda表达式允许您更紧凑地表达单方法接口(称为功能接口)的实例。 方法引用为已经具有名称的方法提供易于阅读的lambda表达式。 默认方法允许将新功能添加到库的接口,并确保与为这些接口的旧版本编写的代码的二进制兼容性。 重复注释提供了对同一声明或类型使用多次应用相同注释类型的功能。 类型注释提供了在使用类型的任何地方应用注释的功能,而不仅仅是在声明上。与可插拔类型系统一起使用时,此功能可以改进代码的类型检查。 改进的类型推断。 方法参数反射。 2、集合 新java.util.stream包的类提供Stream API以支持对元素流的功能样式操作。Stream API集成到Collections API,可以对集合进行批量操作,例如顺序或并行map-reduce转换。 具有关键冲突的HashMaps的性能改进 3、Compact Profiles包含Java SE平台的预定义子集,并支持不需要在小型设备上部署和运行整个Platform的应用程序。 4、安全 默认情况下启用客户端TLS 1.2 新的变体AccessController.doPrivileged使代码能够断言其特权的子集,而不会阻止堆栈的完整遍历来检查其他权限 更强大的基于密码加密的算法 JSSE服务器的SSL / TLS服务器名称指示(SNI)扩展支持 支持AEAD算法:SunJCE提供程序已得到增强,可支持AES / GCM / NoPadding密码实现以及GCM算法参数。SunJSSE提供商已得到增强,可支持基于AEAD模式的密码套件。请参阅Oracle Providers文档,JEP 115。 KeyStore增强功能,包括新的Domain KeyStore类型java.security.DomainLoadStoreParameter,以及-importpasswordkeytool实用程序的新命令选项 SHA-224消息摘要 增强了对NSA Suite B密码学的支持 更好地支持高熵随机数生成 java.security.cert.PKIXRevocationChecker用于配置X.509证书的吊销检查的新类 适用于Windows的64位PKCS11 Kerberos的新rcache类型5重播缓存 支持Kerberos 5协议转换和约束委派 默认情况下禁用Kerberos 5弱加密类型 用于GSS-API / Kerberos 5机制的未绑定SASL 多个主机名的SASL服务 JNI在Mac OS X上桥接到本机JGSS 在SunJSSE提供商支持更强大的临时DH密钥 支持JSSE的服务器端密码套件首选项定制

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值