数组中的 JNA 结构内存分配不正确
JNA structure memory allocation in array is incorrect
我的问题是内存分配不正确。我认为是因为位在属性之间移动。
这是本机代码:
typedef struct s_xl_channel_config {
char name [32];
unsigned char hwType;
unsigned char hwIndex;
unsigned char hwChannel;
unsigned short transceiverType;
unsigned short transceiverState;
unsigned short configError;
unsigned char channelIndex;
unsigned __int64 channelMask;
unsigned int channelCapabilities;
unsigned int channelBusCapabilities;
unsigned char isOnBus;
unsigned int connectedBusType;
XLbusParams busParams;
unsigned int _doNotUse;
unsigned int driverVersion;
unsigned int interfaceVersion;
unsigned int raw_data[10];
unsigned int serialNumber;
unsigned int articleNumber;
char transceiverName [32];
unsigned int specialCabFlags;
unsigned int dominantTimeout;
unsigned char dominantRecessiveDelay;
unsigned char recessiveDominantDelay;
unsigned char connectionInfo;
unsigned char currentlyAvailableTimestamps;
unsigned short minimalSupplyVoltage;
unsigned short maximalSupplyVoltage;
unsigned int maximalBaudrate;
unsigned char fpgaCoreCapabilities;
unsigned char specialDeviceStatus;
unsigned short channelBusActiveCapabilities;
unsigned short breakOffset;
unsigned short delimiterOffset;
unsigned int reserved[3];
} XL_CHANNEL_CONFIG;
我的java代码是这样的:
@FieldOrder ({"name", "hwType", "hwIndex", "hwChannel", "transceiverType",
"transceiverState", "configError", "channelIndex", "channelMask",
"channelCapabilities", "channelBusCapabilities", "isOnBus", "connectedBusType",
"busParams", "_doNotUse", "driverVersion", "interfaceVersion", "raw_data",
"serialNumber", "articleNumber", "transceiverName", "specialCabFlags",
"dominantTimeout", "dominantRecessiveDelay", "recessiveDominantDelay",
"connectionInfo", "currentlyAvailableTimestamps", "minimalSupplyVoltage",
"maximalSupplyVoltage", "maximalBaudrate", "fpgaCoreCapabilities",
"specialDeviceStatus", "channelBusActiveCapabilities", "breakOffset",
"delimiterOffset", "reserved"})
public class XLchannelConfig extends Structure{
public byte[] name = new byte[32];
public byte hwType;
public byte hwIndex;
public byte hwChannel;
public short transceiverType;
public short transceiverState;
public short configError;
public byte channelIndex;
public Nativelong channelMask;
public int channelCapabilities;
public int channelBusCapabilities;
public byte isOnBus;
public int connectedBusType;
public XLbusParams busParams= new XLbusParams();
public int _doNotUse;
public int driverVersion;
public int interfaceVersion;
public int[] raw_data = new int[(10)];
public int serialNumber;
public int articleNumber;
public byte[] transceiverName = new byte[32];
public int specialCabFlags;
public int dominantTimeout;
public byte dominantRecessiveDelay;
public byte recessiveDominantDelay;
public byte connectionInfo;
public byte currentlyAvailableTimestamps;
public short minimalSupplyVoltage;
public short maximalSupplyVoltage;
public int maximalBaudrate;
public byte fpgaCoreCapabilities;
public byte specialDeviceStatus;
public short channelBusActiveCapabilities;
public short breakOffset;
public short delimiterOffset;
public int[] reserved = new int[3];
public XLchannelConfig() {
super();
}
XLchannelConfig class 位于我用 .toArray()
初始化的数组中。
当我输出属性时,我看到值发生了偏移。看起来这些位已经从一个属性转移到下一个属性。我怀疑是数据类型错误,但我无法确定是哪个。
toString 打印出来:
XLchannelConfig [name=Virtual Channel 1 , hwType=1, hwIndex=0, hwChannel=0, transceiverType=0, transceiverState=0, channelIndex=1, channelMask=0, channelCapabilities=458752, channelBusCapabilities=106496, isOnBus=1, connectedBusType=16777216, driverVersion=67830784, interfaceVersion=0, raw_data=[0, 0, 0, 65536, 0, 0, 0, 0, 0, 0], serialNumber=0, articleNumber=536870912, transceiverName=Virtual CAN , specialCabFlags=0, dominantTimeout=0, reserved=[0, 0, 1442840576], busParams=XLbusParams [busType=536870912]]
XLchannelConfig [name=irtual Channel 2 , hwType=0, hwIndex=1, hwChannel=22, transceiverType=0, transceiverState=0, channelIndex=0, channelMask=0, channelCapabilities=1792, channelBusCapabilities=16777632, isOnBus=0, connectedBusType=65536, driverVersion=264964, interfaceVersion=0, raw_data=[0, 0, 0, 256, 0, 0, 0, 0, 0, 0], serialNumber=0, articleNumber=1444937728, transceiverName=irtual CAN , specialCabFlags=0, dominantTimeout=0, reserved=[0, 0, 0], busParams=XLbusParams [busType=-1591738368]]
症状显示您的映射中多了一个字节。 reserved
字段的最后一个元素包括字节 0x56
,它对应于第二个元素中缺少的字母“V”。所以我们需要寻找那个额外的字节。
头文件总线类型最多只能达到 0x100
。您的输出的总线类型为 0x20000000
,表明错误发生在 XLbusParams
并集之前。它肯定发生在 transcieverName
之前,它显示一个额外的 non-null 字节作为最后一个字符。除了 channelMask
(见下文,将是 4 字节偏移量)之外,映射看起来是正确的。
可以解释单个字节的一种可能的不匹配可能是结构字段的对齐。名称占用 32 个字节,然后是三个 1 字节的字段,后面跟着三个 2 字节的字段。这将具有跨越 4 字节或 8 字节边界的 short
字段之一。您可能会考虑使用不同的 JNA 结构对齐方式,例如 Structure.ALIGN_NONE:
public XLchannelConfig() {
super(Structure.ALIGN_NONE);
}
其他映射评论:
C头中的channelMask
字段是一个明确的64位类型(int64
),因此应该直接映射到Java的64位long
。只有在本机类型为 long
时才应使用 NativeLong
作为映射。这可以是 32 位或 64 位,具体取决于操作系统和位数。这将(可能)under-allocate 4 个字节,但是,可能不是问题。
在 API 中的头文件副本中,我没有看到您包含的 _doNotUse
字段。你确定它应该包括在内吗?这会向映射添加 4 个字节。您确定您复制的头文件与您正在使用的 API 二进制文件的版本匹配吗?
问题的另一个潜在来源是 XLbusParams
类型。 API 表明这是一个具有 int
类型和 32 字节数据的联合。如果您没有正确映射联合(至少是最大的成员)也可能导致偏移。
我的问题是内存分配不正确。我认为是因为位在属性之间移动。
这是本机代码:
typedef struct s_xl_channel_config {
char name [32];
unsigned char hwType;
unsigned char hwIndex;
unsigned char hwChannel;
unsigned short transceiverType;
unsigned short transceiverState;
unsigned short configError;
unsigned char channelIndex;
unsigned __int64 channelMask;
unsigned int channelCapabilities;
unsigned int channelBusCapabilities;
unsigned char isOnBus;
unsigned int connectedBusType;
XLbusParams busParams;
unsigned int _doNotUse;
unsigned int driverVersion;
unsigned int interfaceVersion;
unsigned int raw_data[10];
unsigned int serialNumber;
unsigned int articleNumber;
char transceiverName [32];
unsigned int specialCabFlags;
unsigned int dominantTimeout;
unsigned char dominantRecessiveDelay;
unsigned char recessiveDominantDelay;
unsigned char connectionInfo;
unsigned char currentlyAvailableTimestamps;
unsigned short minimalSupplyVoltage;
unsigned short maximalSupplyVoltage;
unsigned int maximalBaudrate;
unsigned char fpgaCoreCapabilities;
unsigned char specialDeviceStatus;
unsigned short channelBusActiveCapabilities;
unsigned short breakOffset;
unsigned short delimiterOffset;
unsigned int reserved[3];
} XL_CHANNEL_CONFIG;
我的java代码是这样的:
@FieldOrder ({"name", "hwType", "hwIndex", "hwChannel", "transceiverType",
"transceiverState", "configError", "channelIndex", "channelMask",
"channelCapabilities", "channelBusCapabilities", "isOnBus", "connectedBusType",
"busParams", "_doNotUse", "driverVersion", "interfaceVersion", "raw_data",
"serialNumber", "articleNumber", "transceiverName", "specialCabFlags",
"dominantTimeout", "dominantRecessiveDelay", "recessiveDominantDelay",
"connectionInfo", "currentlyAvailableTimestamps", "minimalSupplyVoltage",
"maximalSupplyVoltage", "maximalBaudrate", "fpgaCoreCapabilities",
"specialDeviceStatus", "channelBusActiveCapabilities", "breakOffset",
"delimiterOffset", "reserved"})
public class XLchannelConfig extends Structure{
public byte[] name = new byte[32];
public byte hwType;
public byte hwIndex;
public byte hwChannel;
public short transceiverType;
public short transceiverState;
public short configError;
public byte channelIndex;
public Nativelong channelMask;
public int channelCapabilities;
public int channelBusCapabilities;
public byte isOnBus;
public int connectedBusType;
public XLbusParams busParams= new XLbusParams();
public int _doNotUse;
public int driverVersion;
public int interfaceVersion;
public int[] raw_data = new int[(10)];
public int serialNumber;
public int articleNumber;
public byte[] transceiverName = new byte[32];
public int specialCabFlags;
public int dominantTimeout;
public byte dominantRecessiveDelay;
public byte recessiveDominantDelay;
public byte connectionInfo;
public byte currentlyAvailableTimestamps;
public short minimalSupplyVoltage;
public short maximalSupplyVoltage;
public int maximalBaudrate;
public byte fpgaCoreCapabilities;
public byte specialDeviceStatus;
public short channelBusActiveCapabilities;
public short breakOffset;
public short delimiterOffset;
public int[] reserved = new int[3];
public XLchannelConfig() {
super();
}
XLchannelConfig class 位于我用 .toArray()
初始化的数组中。
当我输出属性时,我看到值发生了偏移。看起来这些位已经从一个属性转移到下一个属性。我怀疑是数据类型错误,但我无法确定是哪个。
toString 打印出来:
XLchannelConfig [name=Virtual Channel 1 , hwType=1, hwIndex=0, hwChannel=0, transceiverType=0, transceiverState=0, channelIndex=1, channelMask=0, channelCapabilities=458752, channelBusCapabilities=106496, isOnBus=1, connectedBusType=16777216, driverVersion=67830784, interfaceVersion=0, raw_data=[0, 0, 0, 65536, 0, 0, 0, 0, 0, 0], serialNumber=0, articleNumber=536870912, transceiverName=Virtual CAN , specialCabFlags=0, dominantTimeout=0, reserved=[0, 0, 1442840576], busParams=XLbusParams [busType=536870912]]
XLchannelConfig [name=irtual Channel 2 , hwType=0, hwIndex=1, hwChannel=22, transceiverType=0, transceiverState=0, channelIndex=0, channelMask=0, channelCapabilities=1792, channelBusCapabilities=16777632, isOnBus=0, connectedBusType=65536, driverVersion=264964, interfaceVersion=0, raw_data=[0, 0, 0, 256, 0, 0, 0, 0, 0, 0], serialNumber=0, articleNumber=1444937728, transceiverName=irtual CAN , specialCabFlags=0, dominantTimeout=0, reserved=[0, 0, 0], busParams=XLbusParams [busType=-1591738368]]
症状显示您的映射中多了一个字节。 reserved
字段的最后一个元素包括字节 0x56
,它对应于第二个元素中缺少的字母“V”。所以我们需要寻找那个额外的字节。
头文件总线类型最多只能达到 0x100
。您的输出的总线类型为 0x20000000
,表明错误发生在 XLbusParams
并集之前。它肯定发生在 transcieverName
之前,它显示一个额外的 non-null 字节作为最后一个字符。除了 channelMask
(见下文,将是 4 字节偏移量)之外,映射看起来是正确的。
可以解释单个字节的一种可能的不匹配可能是结构字段的对齐。名称占用 32 个字节,然后是三个 1 字节的字段,后面跟着三个 2 字节的字段。这将具有跨越 4 字节或 8 字节边界的 short
字段之一。您可能会考虑使用不同的 JNA 结构对齐方式,例如 Structure.ALIGN_NONE:
public XLchannelConfig() {
super(Structure.ALIGN_NONE);
}
其他映射评论:
C头中的channelMask
字段是一个明确的64位类型(int64
),因此应该直接映射到Java的64位long
。只有在本机类型为 long
时才应使用 NativeLong
作为映射。这可以是 32 位或 64 位,具体取决于操作系统和位数。这将(可能)under-allocate 4 个字节,但是,可能不是问题。
在 API 中的头文件副本中,我没有看到您包含的 _doNotUse
字段。你确定它应该包括在内吗?这会向映射添加 4 个字节。您确定您复制的头文件与您正在使用的 API 二进制文件的版本匹配吗?
问题的另一个潜在来源是 XLbusParams
类型。 API 表明这是一个具有 int
类型和 32 字节数据的联合。如果您没有正确映射联合(至少是最大的成员)也可能导致偏移。