【问题标题】:JNA Structure inside a structure结构内的 JNA 结构
【发布时间】:2016-08-04 10:19:11
【问题描述】:

我对 JNA 编程很陌生。我有一个本机代码如下

int Data(int Number, aaa *Data, int* error);

typedef struct {
    uint8 Storage;
    LStr path;
    int32 chart;
    int32 strt;
    LStr val;
    int32 timedata;
    } aaa;

typedef struct {
    int32   cnt;    /*num of bytes that follow*/    
    uChar   str[1]; 
} LStrval, *LStrPtr, **LStr;

如何使用 JNA 从 Java 调用此本机函数。我尝试了几个选项,但我没有得到结果。我尝试过的选项之一如下。

接口函数

public int SetStorage_Data(int num,Storage_Data.ByReference data, Pointer error);

 public class Storage_Data extends Structure{
        public static class ByReference extends Storage_Data implements Structure.ByReference {}

        public byte storage;
        public Stringtype.ByReference savepath;
        public int chart;
        public int strt;
        public Stringtype.ByReference val;
        public int timedata;

        @Override
        protected List getFieldOrder() {
            return Arrays.asList("storage", "savepath","chart",
                    "strt","val","timedata");
        }
    }



public class Stringtype extends Structure{
        public static class ByReference extends Stringtype implements Structure.ByReference {

            public ByReference(int buffersize) {
                super(buffersize);
                // TODO Auto-generated constructor stub
            }}

        public int count;
        public byte[] str;

        public Stringtype(int buffersize) {
            str = new byte[buffersize];
            count = str.length;
            allocateMemory();
        }

        @Override
        protected List getFieldOrder() {
            return Arrays.asList("count", "str");
        }
    }

还有 Java 调用

InjectionAnalyzerInterfaces.Storage_Data.ByReference storagedata = new InjectionAnalyzerInterfaces.Storage_Data.ByReference();

 int len= string.length;
 InjectionAnalyzerInterfaces.Stringtype.ByReference savepath = new InjectionAnalyzerInterfaces.Stringtype.ByReference(len);

            byte[] stringbyte = string.getBytes();
            System.arraycopy(stringbyte, 0, savepath.str, 0, bytes);
            storagedata.savepath = savepath;
            storagedata.chart = 1;
            storagedata.strt =1;
            String temp= "all";
            byte[] strtbyte = temp.getBytes();
            int dd = strtbyte.length;
            InjectionAnalyzerInterfaces.Stringtype.ByReference stra = new InjectionAnalyzerInterfaces.Stringtype.ByReference(dd);
            System.arraycopy(strtbyte, 0,  stra.str,0, dd);
            storagedata.strt = stra;


            storagedata.tdata = 0;

            Pointer error = new Memory(5);

            int status1 =  lib.Set_Config_Storage_Data(deviceNumber, storagedata, error);

请帮帮我。提前谢谢你

【问题讨论】:

  • 我建议您首先对这些字段使用Pointer,然后使用各种Pointer 访问方法以您想要的方式提取和格式化数据。一旦您了解了取消引用的级别,您就可以找出最明智的映射方式。但是,您有一个基本问题,因为您的字段是 struct**,JNA 不会识别它,所以对 Structure.read/write 的所有调用完全取决于您执行。
  • @technomage 是使用Pointer.getPointer(0) 还是PointerByReference.getValue() 更好?
  • 只有在将指针的地址作为参数传递给某物时,才应使用PointerByReference。如果您刚刚将void** 作为某个字段,请使用Pointer

标签: java pointers structure jna


【解决方案1】:

在定义LStrVal 时,您需要初始化原始数组字段,以便 JNA 知道要分配多少内存(至少开始时):

public byte str = new byte[1];

您需要重写Structure.read() 来做正确的事情,并提供一个基于Pointer 的构造函数以在从本机内存初始化后读取:

public void read() {
    count = (int)readField("count");
    str = new byte[count];
    super.read();
}

public LStr(Pointer p) {
    super(p);
    read();
}

最后,您的包含结构有 struct** 字段(不知道为什么),您必须将其映射到 Pointer,并提供一个方便的函数来实际转换为您想要的结构:

public Pointer savepath;
public LStr getSavepath() {
    return savepath != null ? new LStr(savepath.getPointer(0)) : null;
}

【讨论】:

    【解决方案2】:

    你在正确的轨道上。

    您需要将内部结构(LStrVal)声明为其自己的结构类。看起来您已经使用 Stringtype 结构完成了该操作,但您需要在其中更改一些内容:

    • 用 int arg 去掉构造函数。您的 C 结构将 byte[] 数组的大小指定为 1,只需使用该常量即可。
    • 您需要一个调用super() 的无参数构造函数
    • 您需要一个带有指针 arg p 的构造函数,该构造函数调用 super(p)
    • 您不需要 ByReference 部分

    然后你应该为那些结构指针使用PointerByReference 类型的外部结构,然后在你的主代码中,使用new Stringtype(pbr.getValue()) 将指针转换为必要的类。

    或者,正如@technomage 建议的那样,您可以使用指针类型,然后使用getValue() 代替getPointer(0)。底线是您需要一个指针(指向指针)作为您的实例变量。

    【讨论】:

    • LStr 的类型为struct**,它not 映射到Structure.ByReference(在结构字段的上下文中,它是struct*)。
    • 刚刚重新阅读并注意到这一点并适当地编辑了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    • 1970-01-01
    • 2015-07-03
    相关资源
    最近更新 更多