JNA的使用方法简介(struct和union)

最近因为项目开发需要,用了到JNA的相关技术。下面就使用中的一些体会进行一下简单的总结。

基本知识链接

http://blog.csdn.net/shendl/article/details/3599849
http://blog.csdn.net/challange_world/article/details/8443007
http://blog.csdn.net/xueerfei008/article/details/9898657

遇到的主要问题
1.结构体内嵌结构体数组的问题

按照网上的教程,对于嵌套的结构体,需要定义为 xxx.ByValue;但实际验证过程中,定义成xxx.ByValue方式时,会出现java结构体和c语言结构体内存大小不一致的情况;只需要定义成xxx即可。如下所示

public class RwResult extends Structure
{
    public int tagNum;
    public TagResult[] tagResult = new TagResult[8];

    {
        for(int i = 0; i < 68; i++)
        {
            tagResult[i] = new TagResult();
        }
    }
    public static class ByValue  extends RwResult implements Structure.ByValue{ }
    public static class ByReference extends RwResult implements Structure.ByReference{ }
}
2.对于联合体的使用

下面是JNA官网上的一段原话

==Represents a native union. When writing to native memory, the field corresponding to the type passed to setType(java.lang.Class) will be written to native memory. Upon reading from native memory, Structure, String, or WString fields will not be initialized unless they are the current field as identified by a call to setType(java.lang.Class). The current field is always unset by default to avoid accidentally attempting to read a field that is not valid. In the case of a String, for instance, an invalid pointer may result in a memory fault when attempting to initialize the String==

也就是说,在使用联合体的成员时,需要提前设定将要使用的成员类型,然后再使用。否则,虽然能够成功设置值,并且编译时没有报错,但是没有办法传真正入到内存中。
例如:

        rwPara.rwInfo.setType(ReadOpInfo.class);
        rwPara.rwInfo.readOpInf.opId = 0x10;
        rwPara.rwInfo.readOpInf.mb = 0x11;
        rwPara.rwInfo.readOpInf.offset = 0x12;
        rwPara.rwInfo.readOpInf.len = 0x13;

上面代码中,readOpInfo是一个联合体,在使用其中的某一个类型ReadOpInfo时,需要提前设定该联合体类型,然后再给联合体内的成员赋值。

上面的联合体是一个传入参数,也就是说我提前知道我要使用哪个类型,所以可以先设置。那么问题来了,如果我的联合体是一个传出参数,不知道传出来的是什么类型,怎么办?
比如:

        RwResult.ByReference rwresult = new RwResult.ByReference();
        getResult(0,0,rwresult);//先传入一块内存
        rwresult.rwOpResult.SetType(ReadCustomResult.class);//然后设置联合体类型
        tmp = rwresult.rwOpResult.xxx //访问某个ReadCustomResult成员

很遗憾,jna不支持这种方式,我们并不能将想要结果取出来。
所以,我们只能用下面的方式

        RwResult.ByReference rwresult = new RwResult.ByReference();
        rwresult.rwOpResult.SetType(ReadCustomResult.class);//先设置联合体类型
        getResult(0,0,rwresult);//传入一块内存

        tmp = rwresult.rwOpResult.xxx //访问某个ReadCustomResult成员

也就是说,再不确定传出参数的类型时,我们没办法正确得到想要的数据。这让人很困惑,在C语言中这是一个很普通的应用场景,JNA却没有办法解决。

也可能是我那些地方没有理解,没有找到正确的使用方法,或者JNA有其他的替代方案。

还好,项目中通过其他的规避方式,能够提前知道返回的联合体的类型,使用JNA的联合体的不足给解决了。不过,后来大家又提出一个方案,能不能将传入传出参数用第三方跨平台跨语言工具进行序列化和反序列化,这后续会进行下预研。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值