使用 JNA 加载的结构定义字段错误
Structure loaded using JNA defining fields wrong
我以前没有使用过 JNA,但我想我会用我正在使用的第 3 方 DLL 试一试。我希望我可以提供我用 JNA 调用的函数的源代码,但遗憾的是我没有这个软件,所以我确定我可以分发什么。
我需要的结构比较long/complex,只是一个警告。我没有包含加载此结构所需的功能,因为它们似乎可以正常工作并且没有问题。这是原始的 C 结构:
struct TSurfObjectInfos
{
unsigned long ulSize; // size of the structure
int Type; // studiable type
char strName[31]; // name of the studiable
char strOperatorName[31]; // name of the operator who
// measured the studiable
short nAcquisitionType; // which kind of sensor has been used
// for the measure
short nTracking; // 0: normal tracking
// 1: extended tracking
short nSpecialPoints; // 0: normal
// 1: non-measured points
int bAbsolute; // FALSE: relatives values
// TRUE: absolutes values
float fGaugeResolution; // 0: resolution not set
long nZMin; // min (resampled) value
long nZMax; // max (resampled) value
long nXCount; // number of points by column
long nYCount; // number of points by row
long nWCount; // number of points by depth (for hyperpectral measurements)
float fXStep; // step
float fYStep; // step
float fZStep; // step
float fXOffset; // offset
float fYOffset; // offset
float fZOffset; // offset
char strXAxisName[17]; // name of the X axis
char strYAxisName[17]; // name of the Y axis
char strZAxisName[17]; // name of the Z axis
TUNIT tXAxisUnit; // X axis unit
TUNIT tYAxisUnit; // Y axis unit
TUNIT tZAxisUnit; // Z axis unit
char strXAxisUnknownUnit[17]; // if unknown X unit, unit is present in this field
char strYAxisUnknownUnit[17]; // if unknown Y unit, unit is present in this field
char strZAxisUnknownUnit[17]; // if unknown Z unit, unit is present in this field
int bInverted; // are the values inverted ?
short nRectified; //
short nSecond; // date-time of the measure
short nMinute;
short nHour;
short nDay;
short nMonth;
short nYear;
float fMeasureLength; // length (in seconds) of the measure
char ClientInfo[128]; // client informations
short nCommentSize; // size in bytes of the comment
// *** T Axis ******************
// *** only used with series ***
float fTStep; // step
float fTOffset; // offset
int tTAxisUnit; // T axis unit
char strTAxisUnknownUnit[14]; // if unknown T unit, unit is present in this field
char strTAxisName[14]; // name of the T axis
// *** T Axis ******************
};
typedef struct TSurfObjectInfos TSurfObjectInfos;
这是我的 Java 实现:
@FieldOrder({ "unsignedSize",
"type",
"name",
"operator",
"sensorType",
"trackingType",
"specialPointType",
"absolute",
"gaugeResolution",
"zMin", "zMax",
"xCount", "yCount", "wCount",
"fXStep", "fYStep", "fZStep",
"xOffset", "yOffset", "zOffset",
"xAxisName", "yAxisName", "zAxisName",
"xAxisUnit", "yAxisUnit", "zAxisUnit",
"strXAxisUnknownUnit", "strYAxisUnknownUnit", "strZAxisUnknownUnit",
"inverted",
"rectified",
"second", "minute", "hour", "day", "month", "year", "fMeasureLength",
"clientInfo",
"commentSize",
"tStep", "tOffset", "tAxisUnit", "strTAxisUnknownUnit", "tAxisName"})
public class StudiableInfo extends Structure {
private static final int DATA_SIZE = 339;
/**
* Unsigned byte size of structure.
*/
@Getter public NativeLong unsignedSize = new NativeLong(DATA_SIZE, true);
/**
* Type of surface.
*/
@Getter public int type;
/**
* Name of surface (maximum length of 31).
*/
@Getter public char[] name = new char[31];
/**
* Name of operator who measured the surface (maximum length of 31).
*/
@Getter public char[] operator = new char[31];
/**
* Type of sensor used for measuring the surface.
*/
@Getter public short sensorType;
/**
* Type of tracking used in measurements.
*/
@Getter public short trackingType;
/**
* Special point type, and whether there are non-measured points.
*/
@Getter public short specialPointType;
/**
* Defines if surface has absolute values.
*/
@Getter public boolean absolute;
/**
* Gauge resolution value. Defined as 0 if resolution not set.
*/
@Getter public float gaugeResolution;
/**
* Minimum (resampled) value.
*/
@Getter public NativeLong zMin = new NativeLong();
/**
* Maximum (resampled) value.
*/
@Getter public NativeLong zMax = new NativeLong();
/**
* Number of points by column.
*/
@Getter public NativeLong xCount = new NativeLong();
/**
* Number of points by row.
*/
@Getter public NativeLong yCount = new NativeLong();
/**
* Number of points by depth (for hyperpectral measurements).
*/
@Getter public NativeLong wCount = new NativeLong();
/**
* X-axis step value.
*/
@Getter public float fXStep;
/**
* Y-axis step value.
*/
@Getter public float fYStep;
/**
* Z-axis step value.
*/
@Getter public float fZStep;
/**
* X-axis offset.
*/
@Getter public float xOffset;
/**
* X-axis offset.
*/
@Getter public float yOffset;
/**
* X-axis offset.
*/
@Getter public float zOffset;
/**
* Name of the X-axis (max size of 17 bytes).
*/
@Getter public char[] xAxisName = new char[17];
/**
* Name of the Y-axis (max size of 17 bytes).
*/
@Getter public char[] yAxisName = new char[17];
/**
* Name of the Z-axis (max size of 17 bytes).
*/
@Getter public char[] zAxisName = new char[17];
/**
* X-axis measurement units.
*/
@Getter public int xAxisUnit;
/**
* Y-axis measurement units.
*/
@Getter public int yAxisUnit;
/**
* Z-axis measurement units.
*/
@Getter public int zAxisUnit;
/**
* If unknown X-axis unit from enum, unit is present in this field (max size of 17 bytes).
*/
@Getter public char[] strXAxisUnknownUnit = new char[17];
/**
* If unknown Y-axis unit from enum, unit is present in this field (max size of 17 bytes).
*/
@Getter public char[] strYAxisUnknownUnit = new char[17];
/**
* If unknown Z-axis unit from enum, unit is present in this field (max size of 17 bytes).
*/
@Getter public char[] strZAxisUnknownUnit = new char[17];
/**
* Defines if the studiable values are inverted.
*/
@Getter public boolean inverted;
/**
* Defines if the studiable is levelled.
*/
@Getter public short rectified;
/**
* Seconds value at recorded time of measurement.
*/
@Getter public short second;
/**
* Minutes value at recorded time of measurement.
*/
@Getter public short minute;
/**
* Hour value at recorded time of measurement.
*/
@Getter public short hour;
/**
* Day at recorded time of measurement.
*/
@Getter public short day;
/**
* Month at recorded time of measurement.
*/
@Getter public short month;
/**
* Year at recorded time of measurement.
*/
@Getter public short year;
/**
* Length (in seconds) of the measure.
*/
@Getter public float fMeasureLength;
/**
* Client information (max size of 128 bytes).
*/
@Getter public char[] clientInfo = new char[128];
/**
* Size in bytes of the comment.
*/
@Getter public short commentSize;
// *** T Axis ******************
// *** only used with series ***
/**
* Step value of T-axis.
*/
@Getter public float tStep;
/**
* Offset of T-axis.
*/
@Getter public float tOffset;
/**
* T-axis measurement units.
*/
@Getter public int tAxisUnit;
/**
* If unknown T-axis unit from enum, unit is present in this field (max size of 14 bytes).
*/
@Getter public char[] strTAxisUnknownUnit = new char[14];
/**
* Name of the T-axis (max size of 14 bytes).
*/
@Getter public char[] tAxisName = new char[14];
// *** T Axis ******************
}
我觉得一切都很好,但在实际加载和查看结构时,唯一正确的字段是 type
成员。从那时起,其他所有字段似乎都是无效数据或垃圾数据。但是,它是一致的,总是输出相同的一组无效数据。
我担心这可能是因为导入功能在内部起作用。您会注意到有一个 ulSize
字段,我猜它可以用于映射结构中的内存?因此,一旦使用 JNA 或 Java 的内存处理,函数内部可能不会将内存映射到正确的位置。虽然因为我对 JNA 还是新手,所以我不太确定这是否是一个可能的问题。
我也在想,也许原生 C long
类型和 JNA NativeLong
类型之间存在转换问题?但我还是不太确定。我什至尝试用 long
替换 NativeLong
,但它似乎仍然不起作用。
如果我能提供更多信息,请告诉我。我不想用太多可能毫无用处的信息来超载。
您的问题最可能的来源是使用 Java 的 char
映射 C char
。他们不一样。 Java 的 char
是字符的 2 字节 UTF-16 映射,而在 C 中,char
是单个字节。
有关更多信息,请参阅概述中 JNA 的 Type Mapping 参考。
您为 C 的 long
选择的 NativeLong
对于 cross-platform 代码通常是好的。
我不知道你的 TUNIT
映射到什么,但如果它是 4 字节类型,int
映射就可以了。
我以前没有使用过 JNA,但我想我会用我正在使用的第 3 方 DLL 试一试。我希望我可以提供我用 JNA 调用的函数的源代码,但遗憾的是我没有这个软件,所以我确定我可以分发什么。
我需要的结构比较long/complex,只是一个警告。我没有包含加载此结构所需的功能,因为它们似乎可以正常工作并且没有问题。这是原始的 C 结构:
struct TSurfObjectInfos
{
unsigned long ulSize; // size of the structure
int Type; // studiable type
char strName[31]; // name of the studiable
char strOperatorName[31]; // name of the operator who
// measured the studiable
short nAcquisitionType; // which kind of sensor has been used
// for the measure
short nTracking; // 0: normal tracking
// 1: extended tracking
short nSpecialPoints; // 0: normal
// 1: non-measured points
int bAbsolute; // FALSE: relatives values
// TRUE: absolutes values
float fGaugeResolution; // 0: resolution not set
long nZMin; // min (resampled) value
long nZMax; // max (resampled) value
long nXCount; // number of points by column
long nYCount; // number of points by row
long nWCount; // number of points by depth (for hyperpectral measurements)
float fXStep; // step
float fYStep; // step
float fZStep; // step
float fXOffset; // offset
float fYOffset; // offset
float fZOffset; // offset
char strXAxisName[17]; // name of the X axis
char strYAxisName[17]; // name of the Y axis
char strZAxisName[17]; // name of the Z axis
TUNIT tXAxisUnit; // X axis unit
TUNIT tYAxisUnit; // Y axis unit
TUNIT tZAxisUnit; // Z axis unit
char strXAxisUnknownUnit[17]; // if unknown X unit, unit is present in this field
char strYAxisUnknownUnit[17]; // if unknown Y unit, unit is present in this field
char strZAxisUnknownUnit[17]; // if unknown Z unit, unit is present in this field
int bInverted; // are the values inverted ?
short nRectified; //
short nSecond; // date-time of the measure
short nMinute;
short nHour;
short nDay;
short nMonth;
short nYear;
float fMeasureLength; // length (in seconds) of the measure
char ClientInfo[128]; // client informations
short nCommentSize; // size in bytes of the comment
// *** T Axis ******************
// *** only used with series ***
float fTStep; // step
float fTOffset; // offset
int tTAxisUnit; // T axis unit
char strTAxisUnknownUnit[14]; // if unknown T unit, unit is present in this field
char strTAxisName[14]; // name of the T axis
// *** T Axis ******************
};
typedef struct TSurfObjectInfos TSurfObjectInfos;
这是我的 Java 实现:
@FieldOrder({ "unsignedSize",
"type",
"name",
"operator",
"sensorType",
"trackingType",
"specialPointType",
"absolute",
"gaugeResolution",
"zMin", "zMax",
"xCount", "yCount", "wCount",
"fXStep", "fYStep", "fZStep",
"xOffset", "yOffset", "zOffset",
"xAxisName", "yAxisName", "zAxisName",
"xAxisUnit", "yAxisUnit", "zAxisUnit",
"strXAxisUnknownUnit", "strYAxisUnknownUnit", "strZAxisUnknownUnit",
"inverted",
"rectified",
"second", "minute", "hour", "day", "month", "year", "fMeasureLength",
"clientInfo",
"commentSize",
"tStep", "tOffset", "tAxisUnit", "strTAxisUnknownUnit", "tAxisName"})
public class StudiableInfo extends Structure {
private static final int DATA_SIZE = 339;
/**
* Unsigned byte size of structure.
*/
@Getter public NativeLong unsignedSize = new NativeLong(DATA_SIZE, true);
/**
* Type of surface.
*/
@Getter public int type;
/**
* Name of surface (maximum length of 31).
*/
@Getter public char[] name = new char[31];
/**
* Name of operator who measured the surface (maximum length of 31).
*/
@Getter public char[] operator = new char[31];
/**
* Type of sensor used for measuring the surface.
*/
@Getter public short sensorType;
/**
* Type of tracking used in measurements.
*/
@Getter public short trackingType;
/**
* Special point type, and whether there are non-measured points.
*/
@Getter public short specialPointType;
/**
* Defines if surface has absolute values.
*/
@Getter public boolean absolute;
/**
* Gauge resolution value. Defined as 0 if resolution not set.
*/
@Getter public float gaugeResolution;
/**
* Minimum (resampled) value.
*/
@Getter public NativeLong zMin = new NativeLong();
/**
* Maximum (resampled) value.
*/
@Getter public NativeLong zMax = new NativeLong();
/**
* Number of points by column.
*/
@Getter public NativeLong xCount = new NativeLong();
/**
* Number of points by row.
*/
@Getter public NativeLong yCount = new NativeLong();
/**
* Number of points by depth (for hyperpectral measurements).
*/
@Getter public NativeLong wCount = new NativeLong();
/**
* X-axis step value.
*/
@Getter public float fXStep;
/**
* Y-axis step value.
*/
@Getter public float fYStep;
/**
* Z-axis step value.
*/
@Getter public float fZStep;
/**
* X-axis offset.
*/
@Getter public float xOffset;
/**
* X-axis offset.
*/
@Getter public float yOffset;
/**
* X-axis offset.
*/
@Getter public float zOffset;
/**
* Name of the X-axis (max size of 17 bytes).
*/
@Getter public char[] xAxisName = new char[17];
/**
* Name of the Y-axis (max size of 17 bytes).
*/
@Getter public char[] yAxisName = new char[17];
/**
* Name of the Z-axis (max size of 17 bytes).
*/
@Getter public char[] zAxisName = new char[17];
/**
* X-axis measurement units.
*/
@Getter public int xAxisUnit;
/**
* Y-axis measurement units.
*/
@Getter public int yAxisUnit;
/**
* Z-axis measurement units.
*/
@Getter public int zAxisUnit;
/**
* If unknown X-axis unit from enum, unit is present in this field (max size of 17 bytes).
*/
@Getter public char[] strXAxisUnknownUnit = new char[17];
/**
* If unknown Y-axis unit from enum, unit is present in this field (max size of 17 bytes).
*/
@Getter public char[] strYAxisUnknownUnit = new char[17];
/**
* If unknown Z-axis unit from enum, unit is present in this field (max size of 17 bytes).
*/
@Getter public char[] strZAxisUnknownUnit = new char[17];
/**
* Defines if the studiable values are inverted.
*/
@Getter public boolean inverted;
/**
* Defines if the studiable is levelled.
*/
@Getter public short rectified;
/**
* Seconds value at recorded time of measurement.
*/
@Getter public short second;
/**
* Minutes value at recorded time of measurement.
*/
@Getter public short minute;
/**
* Hour value at recorded time of measurement.
*/
@Getter public short hour;
/**
* Day at recorded time of measurement.
*/
@Getter public short day;
/**
* Month at recorded time of measurement.
*/
@Getter public short month;
/**
* Year at recorded time of measurement.
*/
@Getter public short year;
/**
* Length (in seconds) of the measure.
*/
@Getter public float fMeasureLength;
/**
* Client information (max size of 128 bytes).
*/
@Getter public char[] clientInfo = new char[128];
/**
* Size in bytes of the comment.
*/
@Getter public short commentSize;
// *** T Axis ******************
// *** only used with series ***
/**
* Step value of T-axis.
*/
@Getter public float tStep;
/**
* Offset of T-axis.
*/
@Getter public float tOffset;
/**
* T-axis measurement units.
*/
@Getter public int tAxisUnit;
/**
* If unknown T-axis unit from enum, unit is present in this field (max size of 14 bytes).
*/
@Getter public char[] strTAxisUnknownUnit = new char[14];
/**
* Name of the T-axis (max size of 14 bytes).
*/
@Getter public char[] tAxisName = new char[14];
// *** T Axis ******************
}
我觉得一切都很好,但在实际加载和查看结构时,唯一正确的字段是 type
成员。从那时起,其他所有字段似乎都是无效数据或垃圾数据。但是,它是一致的,总是输出相同的一组无效数据。
我担心这可能是因为导入功能在内部起作用。您会注意到有一个 ulSize
字段,我猜它可以用于映射结构中的内存?因此,一旦使用 JNA 或 Java 的内存处理,函数内部可能不会将内存映射到正确的位置。虽然因为我对 JNA 还是新手,所以我不太确定这是否是一个可能的问题。
我也在想,也许原生 C long
类型和 JNA NativeLong
类型之间存在转换问题?但我还是不太确定。我什至尝试用 long
替换 NativeLong
,但它似乎仍然不起作用。
如果我能提供更多信息,请告诉我。我不想用太多可能毫无用处的信息来超载。
您的问题最可能的来源是使用 Java 的 char
映射 C char
。他们不一样。 Java 的 char
是字符的 2 字节 UTF-16 映射,而在 C 中,char
是单个字节。
有关更多信息,请参阅概述中 JNA 的 Type Mapping 参考。
您为 C 的 long
选择的 NativeLong
对于 cross-platform 代码通常是好的。
我不知道你的 TUNIT
映射到什么,但如果它是 4 字节类型,int
映射就可以了。