使用JNA加载的结构定义字段错误。

huangapple go评论70阅读模式
英文:

Structure loaded using JNA defining fields wrong

问题

我之前没有使用过JNA,但我打算尝试与我正在使用的第三方DLL一起使用。我希望我能提供我使用JNA调用的函数的源代码,但不幸的是,我不拥有这个软件,所以我不确定我可以分发什么。

我需要的结构相当长/复杂,这只是一个警告。我没有包含加载此结构所需的函数,因为它们似乎在工作并且没有问题。这是原始的C结构:

以下是你提供的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;

  /**
   * 无符号字节结构大小。
   */
  @Getter public NativeLong unsignedSize = new NativeLong(DATA_SIZE, true);

  /**
   * 表面类型。
   */
  @Getter public int type;

  /**
   * 表面名称(最大长度为31)。
   */
  @Getter public char[] name = new char[31];

  /**
   * 测量表面的操作员名称(最大长度为31)。
   */
  @Getter public char[] operator = new char[31];

  /**
   * 用于测量表面的传感器类型。
   */
  @Getter public short sensorType;

  /**
   * 测量中使用的跟踪类型。
   */
  @Getter public short trackingType;

  /**
   * 特殊点类型,以及是否存在未测量的点。
   */
  @Getter public short specialPointType;

  /**
   * 定义表面是否具有绝对值。
   */
  @Getter public boolean absolute;

  /**
   * 标尺分辨率值。如果未设置分辨率,则定义为0。
   */
  @Getter public float gaugeResolution;

  /**
   * 最小(重采样)值。
   */
  @Getter public NativeLong  zMin = new NativeLong();
  /**
   * 最大(重采样)值。
   */
  @Getter public NativeLong  zMax = new NativeLong();

  /**
   * 每列的点数。
   */
  @Getter public NativeLong xCount = new NativeLong();
  /**
   * 每行的点数。
   */
  @Getter public NativeLong  yCount = new NativeLong();
  /**
   * 深度方向上的点数(用于高光谱测量)。
   */
  @Getter public NativeLong  wCount = new NativeLong();

  /**
   * X轴步长值。
   */
  @Getter public float fXStep;
  /**
   * Y轴步长值。
   */
  @Getter public float fYStep;
  /**
   * Z轴步长值。
   */
  @Getter public float fZStep;

  /**
   * X轴偏移量。
   */
  @Getter public float xOffset;
  /**
   * Y轴偏移量。
   */
  @Getter public float yOffset;
  /**
   * Z轴偏移量。
   */
  @Getter public float zOffset;

  /**
   * X轴名称(最大大小为17字节)。
   */
  @Getter public char[] xAxisName = new char[17];
  /**
   * Y轴名称(最大大小为17字节)。
   */
  @Getter public char[] yAxisName = new char[17];
  /**
   * Z轴名称(最大大小为17字节)。
   */
  @Getter public char[] zAxisName = new char[17];

  /**
   * X轴测量单位。
   */
  @Getter public int xAxisUnit;
  /**
   * Y轴测量单位。
   */
  @Getter public int yAxisUnit;
  /**
   * Z轴测量单位。
   */
  @Getter public int zAxisUnit;

  /**
   * 如果从枚举中未知X轴单位,则单位存在于此字段中(最大大小为17字节)。
   */
  @Getter public char[] strXAxisUnknownUnit = new char[17];
  /**
   * 如果从枚举中未知Y轴单位,则单位存在于此字段中(最大大小为17字节)。
   */
  @Getter public char[] strYAxisUnknownUnit = new char[17];
  /**
   * 如果从枚举中未知Z轴单位,则单位存在于此字段中(最大大小为17字节)。
   */
  @Getter public char[] strZAxisUnknownUnit = new char[17];

  /**
   * 定义研究值是否被倒置。
   */
  @Getter public boolean inverted;

  /**
   * 定义研究是否被校平。
   */
  @Getter public short rectified;

  /**
   * 测量记录时间的秒值。
   */
  @Getter public short second;
  /**
   * 测量记录时间的分钟值。
   */
  @Getter public short minute;
  /**
   * 测量记录时间的小时值。
   */
  @Getter public short hour;
  /**
   * 测量记录时间的日期。
   */
  @Getter public short day;
  /**
   * 测量记录时间的月份。
   */
  @Getter public short month;
  /**
   * 测量记录时间的年份。
   */
  @Getter public short year;
  /**
   * 测量的长度(以秒为单位)。
   */
  @Getter public float fMeasureLength;

  /**
   * 客户信息(最大大小为128字节)。
   */
  @Getter public char[] clientInfo = new char[

<details>
<summary>英文:</summary>

I haven&#39;t used JNA before, but I figured I would give it a shot with a 3rd party DLL I am working with. I wish I could give the source code for the functions that I call with JNA, but I sadly don&#39;t own this software so I&#39;m sure what I am allowed to distribute.

The structure I need is rather long/complex, just a warning. I did not include the functions I needed to load this struct, as they appear to be working and have no issue. Here is the original C struct:

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;


And here is my Java implementation:

@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 ******************
}


Everything on their own looks fine to me, but when actually loading and looking at the structure, the only field that is correct is the `type` member. From then on, every other field appears to be invalid or garbage data. However, it is consistent and always outputs the same set of invalid data. 
I&#39;m worried that this could be because of the import function works internally. You will notice there is a `ulSize` field that I&#39;m guessing could be used for mapping the memory in the structure? So maybe the function internally is not mapping the memory to the correct location once JNA or Java&#39;s memory handling is being used. Although since I am still new to JNA, I am not quite sure if that is even a possible issue.
I&#39;m also thinking that maybe there is a conversion issue between the native C `long` type and the JNA `NativeLong`? But I&#39;m still not quite sure. I even tried replacing the `NativeLong`&#39;s with `long`s and it still didn&#39;t seem to work.
Let me know if there is more information I can give. I didn&#39;t want to overload with too much information that could&#39;ve been useless.
</details>
# 答案1
**得分**: 1
你问题最可能的来源是在使用Java的`char`映射到C的`char`时出现了问题。它们并不相同。Java的`char`是字符的2字节UTF-16映射,而在C中,`char`是一个字节。
详见JNA的[类型映射](http://java-native-access.github.io/jna/5.6.0/javadoc/overview-summary.html#marshalling)概述中的更多信息。
一般情况下,你对于在C中使用`long`选择的`NativeLong`是可以的,用于跨平台代码。
我不清楚你的`TUNIT`映射到什么类型,但如果它是一个4字节类型,使用`int`映射是可以的。
<details>
<summary>英文:</summary>
The most likely source of your problem is using Java&#39;s `char` mapping for the C `char`.   They aren&#39;t the same.  Java&#39;s `char` is a 2-byte UTF-16 mapping of characters, while in C, a `char` is a single byte.
See JNA&#39;s [Type Mapping](http://java-native-access.github.io/jna/5.6.0/javadoc/overview-summary.html#marshalling) reference in the overview for more.  
Your choice of `NativeLong` for C&#39;s `long` is fine in general for cross-platform code.
I don&#39;t know what your `TUNIT` maps to, but if it&#39;s a 4-byte type, the `int` mapping is fine.
</details>

huangapple
  • 本文由 发表于 2020年8月21日 13:40:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/63517085.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定