我成功地将单字节数组字段作为另一个更大结构的一部分输出,从而获得此结构。但是,当我将此结构作为输入参数传递时,本机代码无法破译字节数组中的数据。我已经验证了本机代码能够在没有jna的情况下成功处理直接调用调用。我需要知道,java中的结构定义有什么问题可能导致这个问题。
详细信息我正在使用第三方库,该库的guid具有以下c结构:
typedef struct GuidType
{
uint8_t data[16];
} GuidType;
guidtype用于其他更大的结构中,是用于执行各种数据操作的常用标识信息。例如
typedef struct DataObjectType1 {
GuidType guid;
const char * detail1;
// various other fields
} DataObjectType1;
typedef struct DataObjectType1Array {
size_t size;
DataObjectType1**data; // array of pointers. Each pointer points to a structure
}
typedef struct DataObjectType2 {
GuidType guid;
const char * detail2;
// various other fields
} DataObjectType2;
第三方库具有以下行的API:
int getAllDataObjectType1Instances(DataObjectType1Array**dataObjectType1Instances);
int getDataObjectType2ForGuid(GuidType guid, DataObjectType2**dataObjectType2);
在阅读了jna文档并使用JNAborator之后,我可以得出以下java jna代码:
GuidType extends Structure {
public byte[] data = new byte[16];
public GuidType(Pointer p){
super(p);
read();
}
public GuidType() { }
}
DataObjectType1 extends Structure {
public GuidType guid;
public String detail1;
// various other fields
// Default constructor and constructor with pointer as argument
}
DataObjectType1Array extends Structure {
public int size;
public Pointer data;
// Default constructor and constructor with pointer as argument
}
DataObjectType2 extends Structure {
public GuidType guid;
public String detail2;
// various other fields
// Default constructor and constructor with pointer as argument
}
// Native API equivalent in Java using JNA
int getAllDataObjectType1Instances(PointerByReference dataObjectType1Instances);
int getDataObjectType2ForGuid(GuidType guid, PointerByReference dataObjectType2Instance);
通过以上代码,我能够成功调用getalldataobjecttype1instances api,该api返回所有dataobjecttype1示例,并在结构中正确初始化所有字段。但是,getdataobjecttype2forguid调用始终失败。代码位于以下行中:
PointerByReference dataObjectType1Instances = new PointerByReference();
int result = libraryInstance.getAllDataObjectType1Instances(dataObjectType1Instances);
if(result == 0){
DataObjectType1Array dataObjectType1Array = new DataObjectType1Array(dataObjectType1Instances.getValue());
Pointer[] pointers = dataObjectType1Array.data.getPointerArray(0, dataObjectType1Array.size);
for(Pointer pointer : pointers){
DataObjectType1 dataObjectType1 = new DataObjectType1(pointer);
System.out.println(Arrays.toString(dataObjectType1.guid.data)); // this shows the correct GUID details
// More print statements that indicate other fields in dataObjectType1 are also initialized correctly.
PointerByReference dataObjectType2PointerByReference = new PointerByReference();
result = libraryInstance.getDataObjectType2ForGuid(dataObjectType1.guid, dataObjectType2PointerByReference); // this always fails. On success, library assigns the address of a DataObjectType2 pointer to dataObjectType2PointerByReference.
// ... Code to extract DataObjectType2 instance from dataObjectType2Reference.
}
}
如上所述,libraryinstance.getdataobjecttype2forguid()调用失败,并出现一个错误,表明实际数据没有传递到本机代码。我还尝试在字节数组字段中使用正确的数据创建一个新的guidtype示例,然后将其传递给getdataobjecttype2forguid(),但没有成功。
我无法确定这里出了什么问题?有人能帮忙吗。如果需要更多的细节或者有什么不清楚的地方,请告诉我。提前谢谢。
编辑不确定它是否重要,但本地库是用C编写的。所以我们在这里处理C结构。
2条答案
按热度按时间ttygqcqt1#
根据这里的另一个答案,我可以通过传递来解决这个问题
GuidType.ByValue
到getDataObjectType2ForGuid
. 守则的修订如下:感谢@daniel widdis对我们的支持。
7qhs6swi2#
我最初的回答是,您需要为
PointerByReference
. 这是一个错误的建议,因为正如您后来指出的,api告诉您它将分配自己的内存并返回指向它的指针。正如您所观察到的,您遇到了一种不寻常的情况,c库希望通过值传递结构。关键线索在于此方法签名:
通常,当您在本机方法调用中看到一个结构时,它是一个指向数据的指针,因此您会看到
GuidType *guid
.默认情况下,jna处理结构
ByValue
在其他结构中声明时(例如在DataObjectType2
)及ByReference
传入方法参数时(通常具有*
指示一个指针——你会看到的GuidType *guid
).如果本机api不同于此默认约定(结构中基于指针的变量或方法调用中的完整结构),则需要显式标记结构
ByValue
或ByReference
.这在jna概述的“结构”标题下进行了讨论。