【问题标题】:JNA cast to struct from void**JNA 从 void 转换为 struct **
【发布时间】:2013-09-23 11:10:19
【问题描述】:

我必须调用一个接收void**作为参数的C库;它将void** 转换为已知结构(取决于函数内部信息),然后分配内存并用数据填充它。

我不知道如何从 Java 中调用它。

以下是一些细节:

结构体:

typedef struct  { 
uint32_t   Size[64];  
uint16_t   *Datas[64]; 
} MyStruct_t;

C 函数

int Cfunc( void **Evt) {
  int i;
  MyStruct_t *s;
  s = (MyStruct_t *) malloc(sizeof(MyStruct_t));
  for (i=0; i<8; i++) {
    (s)->Size[i] = 512;
    (s)->Datas[i] = malloc(512 * sizeof (short));
  }
  for (i=8; i<63; i++) {
    (s)->Size[i] = 0;
    (s)->Datas[i] = NULL;
  }
*Evt = s;
}

我的 JNA 包装类:

public class MyStruct_t extends Structure<MyStruct_t, MyStruct_t.ByValue, MyStruct_t.ByReference > {
/// the number of samples stored in Datas array
public int[] Size = new int[64];
/// the array of Size samples
public ShortByReference[] Datas = new ShortByReference[64];
    public MyStruct_t() {
    super();
    initFieldOrder();
}
protected void initFieldOrder() {
    setFieldOrder(new String[]{"Size", "Datas"});
}
public MyStruct_t(int Size[], ShortByReference Datas[]) {
    super();
    if (Size.length != this.Size.length) 
        throw new IllegalArgumentException("Wrong array size !");
    this.Size = Size;
    if (Datas.length != this.Datas.length) 
        throw new IllegalArgumentException("Wrong array size !");
    this.Datas = Datas;
    initFieldOrder();
}
@Override protected ByReference newByReference() { return new ByReference(); }
@Override protected ByValue newByValue() { return new ByValue(); }
@Override protected MyStruct_t newInstance() { return new MyStruct_t(); }
public static MyStruct_t[] newArray(int arrayLength) {
    return Structure.newArray(MyStruct_t.class, arrayLength);
}
public static class ByReference extends MyStruct_t implements Structure.ByReference {};
public static class ByValue extends MyStruct_t implements Structure.ByValue {};
}

Java 函数声明:

public static native int Cfunc(MyStruct_t.ByReference Evt);
public static native int Cfunc(PointerByReference Evt);

如果我通过 PointerByReference 调用 Cfunc,我可以看到内存已分配并且存在某些内容,但我不知道如何将 (?) 转换为真实结构 (MyStruct_t)。

如果我调用传递MyStruct_t.ByReference 的Cfunc,我发现结构没有很好地分配并且里面的值不是预期的。 我做错了什么?

【问题讨论】:

    标签: java casting struct jna void


    【解决方案1】:

    我发现了错误!我使用的是 jnaerator 中的 Structure 类,我删除了 jnaerator Structure 类并使用了 JNA Structure,现在它可以工作了。

    这里是修改后的 java 类:

    import com.sun.jna.Pointer;
    import com.sun.jna.Structure;
    import com.sun.jna.ptr.ShortByReference;
    
    public class t_t extends Structure {
    public int[] lsize = new int[64];
    public Pointer[] ldata = new Pointer[64];
    public t_t() {
        super();
        initFieldOrder();
    }
    protected void initFieldOrder() {
        setFieldOrder(new String[]{"size", "data"});
    }
    public t_t(int size[], Pointer data[]) {
        super();
        if (size.length != this.lsize.length) 
            throw new IllegalArgumentException("Wrong array size !");
        this.lsize = size;
        if (data.length != this.ldata.length) 
            throw new IllegalArgumentException("Wrong array size !");
        this.ldata = data;
        initFieldOrder();
    }
        public t_t(Pointer p){
           super(p);
           read();
        }
        public short[] getData(int i) {
            if (this.lsize[i] == 0) return null;
            return this.ldata[i].getShortArray(0, this.lsize[i]);
        }
        public int getSize(int i) {
            return this.lsize[i];
        }
    public static class ByReference extends t_t implements Structure.ByReference {
    
    };
    public static class ByValue extends t_t implements Structure.ByValue {
    
    };
    }
    

    感谢 technomage 的提示! p1906

    【讨论】:

      【解决方案2】:

      为了清楚起见,您提供的是指针的地址。被调用者将指针值设置为它分配的结构的地址。

      首先,您传递指针的地址(a.k.a PointerByReference):

      public static native int Cfunc(PointerByReference Evt);
      

      然后,提取“返回”的指针值:

      PointerByReference pref = new PointerByReference();
      lib.CFunc(pref);
      Pointer p = pref.getValue();
      

      然后,您可以根据“返回的”指针值创建结构的新实例:

      MyStruct s = new MyStruct(p);
      

      当然,这需要您为结构实现基于 Pointer 的 ctor:

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

      【讨论】:

      • 我尝试为我的结构实现基于指针的构造函数,但收到以下错误:error: constructor Structure in class Structure&lt;S,V,R&gt; cannot be applied to given types; super(p); required: no arguments found: Pointer reason: actual and formal argument lists differ in length where S,V,R are type-variables: S extends Structure&lt;S,V,R&gt; declared in class Structure V extends S declared in class Structure R extends S declared in class Structure
      猜你喜欢
      • 2013-03-05
      • 2020-06-24
      • 2023-03-16
      • 2012-04-28
      • 2019-03-15
      • 2016-10-07
      • 2013-08-29
      • 2012-11-03
      • 1970-01-01
      相关资源
      最近更新 更多