我正在尝试在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
对象。我想我可以找出Name
和Picture
字段,但我将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]));
我无法在结构定义中直接使用ByteBuffer
或PointerArray
,因此我不得不依赖Pointer
。
答案 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
。