java高级用法之:JNA中的Function
简介
在JNA中,为了和native的function进行映射,我们可以有两种mapping方式,第一种是interface mapping,第二种是direct mapping。虽然两种方式不同,但是在具体的方法映射中,我们都需要在JAVA中定义一个和native方法进行映射的方法。
而这个JAVA中的映射在JNA中就是一个function。通过或者function对象,我们可以实现一些非常强大的功能,一起看看吧。
function的定义
先来看下JNA中Function的定义:
public class Function extends Pointer
可以看到Function实际上是一个Pointer,指向的是native function的指针。
那么怎么得到一个Function的实例呢?
我们知道JNA的流程是先进行Library的映射,然后再对Library中的Function进行映射。所以很自然的我们应该可以从Library中得到Function。
我们看一下根据Library name得到function实例的方法定义:
public static Function getFunction(String libraryName, String functionName, int callFlags, String encoding) {
return NativeLibrary.getInstance(libraryName).getFunction(functionName, callFlags, encoding);
}
这个方法可以接受4个参数,前面两个参数大家应该很熟悉了,第三个参数是callFlags,表示的是函数调用的flags,Function定义了三个callFlags:
public static final int C_CONVENTION = 0;
public static final int ALT_CONVENTION = 0x3F;
public static final int THROW_LAST_ERROR = 0x40;
其中C_CONVENTION表示的是C语言类型的方法调用。
ALT_CONVENTION表示的其他的调用方式。
THROW_LAST_ERROR表示如果native函数的返回值是非零值的时候,将会抛出一个LastErrorException。
最后一个参数是encoding,表示的是字符串的编码方式,实际上指的是 Java unicode和native (const char*) strings 的转换方式。
除了根据Library name获取Function之外,JNA还提供了根据Pointer来获取Function的方法。
public static Function getFunction(Pointer p, int callFlags, String encoding) {
return new Function(p, callFlags, encoding);
}
这里的Pointer指的是一个执行native方法的指针,因为Function本身就是继承自Pointer。所以跟Pointer来创建Function的本质就是在Pointer的基础上添加了一些Function特有的属性。
有了Function的定义,更为重要的是如何通过Function来调用对应的方法。跟反射很类似,Function中也有一个invoke方法,通过调用invoke,我们就可以执行对应的Function的功能。
Function中的invoke方法有两种,一种是通用的返回对象Object,一种是带有返回值的invoke方法,比如invokeString,invokePointer,invokeInt等。
Function的实际应用
Function的实际使用和JAVA中的反射有点类似,其工作流程是首先获得要加载的NativeLibrary,然后从该NativeLibrary中找到要调用的Function,最后invoke该Function的某些方法。
C语言中的printf应该是大家最熟悉的native方法了。我们看一下如何使用Function来调用这个方法吧:
NativeLibrary lib = NativeLibrary.getInstance(Platform.C_LIBRARY_NAME);
Function f = lib.getFunction("printf");
try {
f.invoke(getClass(), new Object[] { getName() });
fail("Invalid return types should throw an exception");
} catch(IllegalArgumentException e) {
// expected
}
可以看到调用的流程非常简洁。如果是用interface Mapping或者direct Mapping的形式,我们还需要自定义一个interface或者class,并且在其中定义一个相应的java方法映射。但是如果使用Function的话,这些都不需要了。我们直接可以从NativeLibrary中拿到对应的函数,并最终调用其中的方法。
C语言中的printf的原型如下:
# include <stdio.h>
int printf(const char *format, ...);
printf带有返回值的,如果要输出这个返回值,则可以调用Function中的invokeInt命令。我们再来看一个有返回值的调用例子:
NativeLibrary lib = NativeLibrary.getInstance(Platform.C_LIBRARY_NAME);
Function f = lib.getFunction("printf");
Object[] args = new Object[Function.MAX_NARGS+1];
// Make sure we don't break 'printf'
args[0] = getName();
try {
f.invokeInt(args);
fail("Arguments should be limited to " + Function.MAX_NARGS);
} catch(UnsupportedOperationException e) {
// expected
}
总结
使用Function可以减少手写Mapping的工作,在某些情况下是非常好用的,但是Function的invoke支持TypeMapper,并不支持FunctionMapper,所以在使用中还是有一些限制。
大家可以在使用过程中酌情考虑。
本文已收录于 http://www.flydean.com/07-jna-function/
最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!
java高级用法之:JNA中的Function的更多相关文章
- java高级用法之:JNA中的Structure
目录 简介 native中的struct Structure 特殊类型的Structure 结构体数组作为参数 结构体数组作为返回值 结构体中的结构体 结构体中的数组 结构体中的可变字段 结构体中的只 ...
- java高级用法之:JNA中的回调
目录 简介 JNA中的Callback callback的应用 callback的定义 callback的获取和应用 在多线程环境中使用callback 总结 简介 什么是callback呢?简单点说 ...
- java高级用法之:JNA中的Memory和Pointer
目录 简介 Pointer 特殊的Pointer:Opaque Memory 总结 简介 我们知道在native的代码中有很多指针,这些指针在JNA中被映射成为Pointer.除了Pointer之外, ...
- java高级用法之:JNA类型映射应该注意的问题
目录 简介 String Buffers,Memory,数组和Pointer 可变参数 总结 简介 JNA提供JAVA类型和native类型的映射关系,但是这一种映射关系只是一个大概的映射,我们在实际 ...
- java高级用法之:在JNA中将本地方法映射到JAVA代码中
目录 简介 Library Mapping Function Mapping Invocation Mapping 防止VM崩溃 性能考虑 总结 简介 不管是JNI还是JNA,最终调用的都是nativ ...
- java高级用法之:在JNA中使用类型映射
目录 简介 类型映射的本质 TypeMapper NativeMapped 总结 简介 JNA中有很多种映射,library的映射,函数的映射还有函数参数和返回值的映射,libary和函数的映射比较简 ...
- java高级用法之:调用本地方法的利器JNA
目录 简介 JNA初探 JNA加载native lib的流程 本地方法中的结构体参数 总结 简介 JAVA是可以调用本地方法的,官方提供的调用方式叫做JNI,全称叫做java native inter ...
- java 高级用法整理
一.retentionpolicy.class vs runtime区别 java5,增加了注解的功能:其中retentionpolicy注解的生命周期,提供了三种选择策略 source.class和 ...
- java高级用法之:无所不能的java,本地方法调用实况
目录 简介 JDK的本地方法 自定义native方法 总结 简介 相信每个程序员都有一个成为C++大师的梦想,毕竟C++程序员处于程序员鄙视链的顶端,他可以俯视任何其他语言的程序员. 但事实情况是,无 ...
随机推荐
- SpringMVC常用的注解有哪些?
@RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上.用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径. @RequestBody:注解实现接收http请求 ...
- RocketMQ实现分布式事务
相关文章:http://www.uml.org.cn/zjjs/201810091.asp(深入理解分布式事务,高并发下分布式事务的解决方案) 三种分布式事务: 1.基于XA协议的两阶段提交 2.消息 ...
- 学习Keepalived(二)
一.keepalived简介 keepalived是集群管理中保证集群高可用的一个服务软件,其功能类似于,用来防止单点故障. 二.vrrp协议2.1 vrrp协议简介 在现实的网络环境中,两台需要通信 ...
- centos 后台 运行jar包方法
后台运行jar包方法: 1.nohup java -jar shareniu.jar & nohup意为后台不挂断运行,与是否账号退出无关 2.nohup java -jar shareniu ...
- vulnhub 靶机 Kioptrix Level 1渗透笔记
靶机下载地址:https://www.vulnhub.com/entry/kioptrix-level-1-1,22/ kali ip 信息收集 先使用nmap收集目标的ip地址 nmap -sP 1 ...
- 顺利通过EMC实验(8)
- google fonts 国内使用解决方案
由于众所周知的原因,国内使用google font库有很大的问题. 解决方案1:使用国内镜像如360网站卫士常用前端公共库CDN服务 优点:使用方便 缺点:目标用户包含国外的开发者,不清楚国外用户的加 ...
- 关于websocket制作聊天室的的一些总结
websocket的总结 在一个聊天室系统中,常常使用websocket作为通信的主要方式.参考地址:https://www.jianshu.com/p/00e... 关于自己的看法:websocke ...
- Python里的引用与拷贝规律
python的可变不可变与各种浅拷贝深拷贝规则,一并梳理. Python一切皆引用 在C++/Java里,int a = 1就是创建变量为a,赋值为1:int b = a就是创建变量b,赋值为a的值. ...
- numpy教程02---ndarray数据和reshape重塑
欢迎关注公众号[Python开发实战], 获取更多内容! 工具-numpy numpy是使用Python进行数据科学的基础库.numpy以一个强大的N维数组对象为中心,它还包含有用的线性代数,傅里叶变 ...