如何使用指向Java的指针填充结构?

时间:2013-07-09 19:22:13

标签: java jna

我正在尝试在C DLL中调用一个函数,该函数具有一个指向结构的指针的函数。此结构(Data)的定义如下:

struct BD
{
    char* Data;
    int Length;
};

struct EE
{
    char* Key;
    BD* Value;
};

struct Data
{
    char* Name;
    BD* Picture;

    // A NULL-terminated array of pointers to EE structures.
    EE** Elements;
};

在Java中,我定义了一些看起来像这样的类:

public static class BD extends Structure implements Structure.ByReference {
    public byte[] Data;
    public int Length;
}

public static class EE extends Structure implements Structure.ByReference {
    public String Key;
    public BD Value;
}

public static class Data extends Structure {
    public String Name;
    public BD Picture;
    public PointerByReference Elements;
}

但现在我不确切知道如何正确填充Data对象。我想我可以找出NamePicture字段,但我将Elements字段设置为什么?我可以创建一个EE个对象的Java数组,但是如何从中获取PointerByReference呢?也许我需要将Elements声明为Pointer[],但是我会为每个getPointer()对象填充EE数组的每个元素吗?但这似乎并不合适?

修改:为了更好地了解我要做的事情:

Data data = new Data();
// Fill in Name and Picture fields.

EE[] elements = new Elements[10];
// Fill in the elements array.

// Now how do I set the Elements field on the data object from the elements array?
data.Elements = ???

Edit2 :以下是我使用technomage帮助解决的问题:

我将Data结构更改为:

public static class Data extends Structure {
    public String Name;
    public BD Picture;
    public Pointer Elements;
}

我的BD结构看起来像这样:

public static class BD extends Structure implements Structure.ByReference {
    public Pointer Data;
    public int Length;
}

要将Java byte[]转换为JNA Pointer,我必须使用ByteBuffer

ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
buf.put(bytes);
bd.Data = Natvie.getDirectBufferPointer(buf);

不幸的是,JNA不喜欢ByteBuffer的结构。

要获取我的元素指针,我需要为每个Pointer对象创建一个EE的数组(请参阅technomage对PointerArray实现的回答):

EE e = new EE();
// Populate e object.
// ...

// Important: ensure that the contents of the objects are written out to native memory since JNA can't do this automatically
e.write();
ptrs.add(e);

// Once each object is setup we can simply take the array of pointers and use the PointerArray
data.Elements = new PointerArray(ptrs.toArray(new Pointer[0]));

我无法在结构定义中直接使用ByteBufferPointerArray,因此我不得不依赖Pointer

1 个答案:

答案 0 :(得分:1)

Elements设为Pointer,然后使用Pointer.getPointerArray(0)检索感兴趣的结构指针。

然后,您需要从每个检索到的Structure初始化每个Pointer(不要忘记致电Structure.read())。

没有办法在指针上自动执行间接,并使用Structure数组结束,但它很简单,可以编码到Structure类的方法中(例如{{1} }})。

修改

示例指针数组实现,用于在写入(而不是读取)时初始化指针数组:

Data.getElements()

您还需要在调用本机函数之前调用class PointerArray extends Memory { private final Pointer[] original; public PointerArray(Pointer[] arg) { super(Pointer.SIZE * (arg.length+1)); this.original = arg; for (int i=0;i < arg.length;i++) { setPointer(i*Pointer.SIZE, arg[i]); } setPointer(Pointer.SIZE*arg.length, null); } } } (您可能会在Structure.write()中执行此操作),因为JNA不知道当您需要同步内存时使用香草PointerArray代替Pointer