简体   繁体   English

JNA从无效转换为结构**

[英]JNA cast to struct from void**

I have to call a C library that receives as parameter a void** ; 我必须调用一个C库,该库接收void**作为参数。 it converts the void** into a known structure (depending on function internal information) then allocates memory and fills it with data. 它将void**转换为已知结构(取决于函数内部信息),然后分配内存并用数据填充它。

I don't know how to call it from Java. 我不知道如何从Java调用它。

Below are some details: 以下是一些详细信息:

The struct: 结构:

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

The C function 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;
}

My JNA wrapper class: 我的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 {};
}

The Java function declaration: Java函数声明:

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

If I call the Cfunc passing a PointerByReference I can see that memory is allocated and something is present but I don't know how to cast (?) it to the real structure (MyStruct_t). 如果我通过PointerByReference调用Cfunc,则可以看到已分配内存并且存在某些内容,但是我不知道如何将其转换为真实结构(MyStruct_t)。

If I call the Cfunc passing a MyStruct_t.ByReference , I find the structure not well allocated and values inside are not the expected. 如果我通过MyStruct_t.ByReference调用MyStruct_t.ByReference ,则发现结构分配不MyStruct_t.ByReference ,并且内部的值不是预期的。 What am I doing wrong? 我究竟做错了什么?

To be clear, you are providing the address of a pointer. 需要明确的是,您正在提供一个指针的地址。 The callee sets the pointer value to the address of a struct which it allocates. 被调用者将指针值设置为它分配的结构的地址。

First, you pass the address of the pointer (aka PointerByReference ): 首先,传递指针的地址(又名PointerByReference ):

public static native int Cfunc(PointerByReference Evt);

Then, you extract the "returned" pointer value: 然后,您提取“返回的”指针值:

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

Then, you can create a new instance of your structure based on the "returned" pointer value: 然后,您可以根据“返回的”指针值创建结构的新实例:

MyStruct s = new MyStruct(p);

This, of course, requires that you implement the Pointer -based ctor for your structure: 当然,这要求您为您的结构实现基于Pointer的ctor:

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

I found the mistake! 我发现了错误! I was using Structure class from jnaerator, I removed the jnaerator Structure class and used JNA Structure and now it works. 我从jnaerator使用Structure类,删除了jnaerator Structure类并使用了JNA Structure,现在它可以工作了。

here is the modified and working java class: 这是经过修改且可以正常工作的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 {

};
}

Thanks technomage for the tip! 感谢技术专家的提示! p1906 p1906

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

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