简体   繁体   English

结构内部的JNA结构

[英]JNA Structure inside a structure

I am quite new to JNA programming. 我对JNA编程很陌生。 I have a native code as below 我有如下的本机代码

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;

How can I call this native function from Java using JNA. 如何使用JNA从Java调用此本机函数。 I tried several options, but I am not getting the results. 我尝试了几种选择,但没有得到结果。 one of the options I tried is below. 我尝试的选项之一如下。

the interface function 接口功能

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");
        }
    }

And the Java call 和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);

Please do help me. 请帮帮我。 Thank you in advance 先感谢您

In defining your LStrVal , you need to initialize the primitive array field so that JNA knows how much memory to allocate (at least to start with): 在定义LStrVal ,您需要初始化原始数组字段,以便JNA知道要分配多少内存(至少LStrVal开始):

public byte str = new byte[1];

You need to override Structure.read() to do the right thing, and provide a Pointer -based constructor to read after initializing from native memory: 您需要重写Structure.read()来做正确的事情,并提供一个基于Pointer的构造函数,以便从本机内存初始化后进行读取:

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

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

Finally, your containing struct has struct** fields (no idea why), which you'll have to map to Pointer , and provide a convenience function to actually convert to your desired structure: 最后,您的包含结构具有struct**字段(不知道为什么),您必须将其映射到Pointer ,并提供便捷功能以实际转换为所需的结构:

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

You're on the right track. 您走在正确的轨道上。

You need to declare the inner structure ( LStrVal ) as its own structure class. 您需要将内部结构( LStrVal )声明为其自己的结构类。 It looks like you've done that with your Stringtype structure but you need to change a few things there: 看起来您已经用Stringtype结构完成了此操作,但是您需要在其中进行一些更改:

  • Get rid of the constructor with the int arg. 使用int arg摆脱构造函数。 Your C structure specifies the size of the byte[] array as 1, just use that constant. 您的C结构将byte[]数组的大小指定为1,只需使用该常数即可。
  • You need a no-arg constructor that calls super() 您需要一个调用super()的无参数构造函数
  • You need a constructor with a Pointer arg p that calls super(p) 您需要一个带有指针arg p的构造函数,该构造函数调用super(p)
  • You don't need the ByReference parts 您不需要ByReference部分

Then the outer structure you should use a PointerByReference type for those structure pointers, and then in your main code, use new Stringtype(pbr.getValue()) to convert the pointer into the necessary class. 然后,外部结构应该为这些结构指针使用PointerByReference类型,然后在主代码中使用new Stringtype(pbr.getValue())将指针转换为必要的类。

Alternately, as @technomage suggests, you could use a Pointer type, and then instead of getValue() you'd use getPointer(0) . 或者,正如@technomage所建议的,您可以使用Pointer类型,然后使用getPointer(0)代替getValue() getPointer(0) Bottom line is that you need a pointer (to a pointer) as your instance variable. 最重要的是,您需要一个指针(指向一个指针)作为实例变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM