java高级用法之JNA中的Function

 更新时间:2022年04月18日 16:16:25   作者:程序那些事  
这篇文章主要介绍了java高级用法之JNA中的Function,JAVA中的映射在JNA中就是一个function。通过或者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来调用这个方法吧:

可以看到调用的流程非常简洁。如果是用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,所以在使用中还是有一些限制。

到此这篇关于java高级用法之JNA中的Function的文章就介绍到这了,更多相关java 中的Function内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MyBatis获取插入记录的自增长字段值(ID)

    MyBatis获取插入记录的自增长字段值(ID)

    本文分步骤给大家介绍了MyBatis获取插入记录的自增长字段值的方法,在文中给大家提到了mybatis返回插入数据的自增长id,需要的朋友可以参考下
    2017-11-11
  • springboot获取微信JSDK签名信息的实现示例

    springboot获取微信JSDK签名信息的实现示例

    本文介绍了如何在Spring Boot应用中获取微信JSDK的签名信息,包括获取接口URL、参数设置、签名算法和获取签名结果的步骤,具有一定的参考价值,感兴趣的可以了解一下
    2023-11-11
  • Java调用DeepSeek api实现方法记录

    Java调用DeepSeek api实现方法记录

    这篇文章主要介绍了如何在Java中调用DeepSeek API,包括在官网获取APIKeys、创建API请求工具类以及处理返回结果的步骤,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-02-02
  • Java中实现在一个方法中调用另一个方法

    Java中实现在一个方法中调用另一个方法

    下面小编就为大家分享一篇Java中实现在一个方法中调用另一个方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-02-02
  • Java的split方法使用详解

    Java的split方法使用详解

    这篇文章主要详细介绍了Java的split方法使用说明,十分的细致全面,有需要的小伙伴可以参考下。
    2015-07-07
  • 浅谈Spring 重定向指南

    浅谈Spring 重定向指南

    本篇文章主要介绍了浅谈Spring 重定向指南,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • 关于synchronized的参数及其含义

    关于synchronized的参数及其含义

    这篇文章主要介绍了synchronized的参数及其含义详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • 一文盘点Java创建实例对象的方式

    一文盘点Java创建实例对象的方式

    Java对象是通过加载、链接、初始化三大步骤来完成对象的创建及初始化,那么接下来就说一下Java创建实例对象的方式有哪几种,文中并通过代码示例讲解的非常详细,需要的朋友可以参考下
    2025-02-02
  • 详解Mybatis Generator的具体使用教程

    详解Mybatis Generator的具体使用教程

    Mybatis Generator可以帮助我们自动生成很多结构化的代码,比如每张表对应的Entity、Mapper接口和Xml文件,可以省去很多繁琐的工作,今天通过本文给大家介绍Mybatis Generator的具体使用教程,感兴趣的朋友一起看看吧
    2022-02-02
  • IDEA2021.2永久激活码最新超详细(激活到2099)

    IDEA2021.2永久激活码最新超详细(激活到2099)

    这篇文章主要介绍了IDEA2021.2永久激活码,是idea2021版最新激活方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09

最新评论