英文:
JNA structure memory allocation in array is incorrect
问题
以下是翻译好的部分:
C代码部分:
typedef struct s_xl_channel_config {
char name [32];
unsigned char hwType;
unsigned char hwIndex;
unsigned char hwChannel;
unsigned short transceiverType;
// ...(后续结构成员)
} XL_CHANNEL_CONFIG;
Java代码部分:
@FieldOrder({"name", "hwType", "hwIndex", "hwChannel", "transceiverType", /*...*/})
public class XLchannelConfig extends Structure {
public byte[] name = new byte[32];
public byte hwType;
public byte hwIndex;
public byte hwChannel;
public short transceiverType;
// ...(后续成员变量)
}
请注意,由于篇幅限制,我只提供了部分代码的翻译。如果您有任何关于代码翻译的问题,请随时向我提问。
英文:
I have the problem that the memory allocation is incorrect. I think so because the bits are shifted between the attributes.
this is the native code:
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;
My java Code is this:
@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();
}
The XLchannelConfig class is in an array that I initialized with .toArray()
.
When I output the attributes, I see that the values are shifted. It looks like the bits have shifted from one attribute to the next. I suspect that it is due to the wrong data type, but I cannot determine which it is.
The toString print this out:
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]]
答案1
得分: 1
以下是翻译好的部分:
症状显示在你的映射中多了一个额外的单字节。reserved
字段的最后一个元素包括字节 0x56
,对应于第二个元素缺失的字母 "V"。所以我们需要找出这个额外的字节。
头文件中的总线类型仅到达 0x100
。你的输出将总线类型表示为 0x20000000
,这表明错误发生在 XLbusParams
联合体之前。肯定是在 transcieverName
之前发生的,它显示出额外的非空字节作为最后一个字符。除了 channelMask
(见下文,将是 4 字节的偏移量),映射看起来是正确的。
可能导致一个单字节不匹配的原因是结构字段的对齐方式。名称占用 32 字节,然后是三个 1 字节字段,跟着是三个 2 字节字段。这将使其中一个 short
字段越过 4 字节或 8 字节的边界。你可以考虑使用不同的 JNA 结构对齐方式,例如 Structure.ALIGN_NONE:
public XLchannelConfig() {
super(Structure.ALIGN_NONE);
}
其他映射注释:
C 头文件中的 channelMask
字段是显式的 64 位类型(int64
),因此应直接映射到 Java 的 64 位 long
。只有在本机类型为 long
时,才应该使用 NativeLong
作为映射。这可以是 32 位或 64 位,具体取决于操作系统和位数。但这可能会少分配 4 个字节,并且可能不是问题的原因。
在 API 的头文件副本中,我没有看到你包含的 _doNotUse
字段。你确定它应该被包括吗?这会将 4 个字节添加到映射中。你确定你复制的头文件与你使用的 API 二进制版本匹配吗?
问题的另一个潜在来源是 XLbusParams
类型。API 显示这是一个带有 int
类型和 32 字节数据的联合。如果你没有正确映射联合(至少是最大的成员),这也可能导致偏移。
英文:
The symptoms show an an extra single byte in your mapping. The last element of the reserved
field includes the byte 0x56
which corresponds to the letter "V" missing from the second element. So we need to look for that extra byte.
The header file bus types go only up to 0x100
. Your output has the bus type as 0x20000000
suggesting the error is occurring before the XLbusParams
union. It's definitely occurring before the transcieverName
which shows an extra non-null byte as the last character. Other than channelMask
(see below, would be 4-byte offset) the mappings look correct.
One possible mismatch that could explain a single byte could be alignment of the structure fields. The name takes 32 bytes, and then there are three 1-byte fields followed by three 2-byte fields. This would have one of the short
fields crossing a 4-byte or 8-byte boundary. You might consider using different JNA Structure alignments, such as Structure.ALIGN_NONE:
public XLchannelConfig() {
super(Structure.ALIGN_NONE);
}
Other mapping comments:
The channelMask
field in the C header is an explicit 64-bit type (int64
), and thus should be directly mapped to Java's 64-bit long
. The only time you should use NativeLong
as a mapping is when the native type is long
. This can be either 32-bit or 64-bit, depending on both operating system and bitness. This would (possibly) under-allocate by 4 bytes, however, and may not be the problem.
In copies of the header file in the API, I do not see the _doNotUse
field that you include. Are you sure it should be included? This adds 4 bytes to the mapping. Are you certain the header file you've copied matches the version of the API binary that you're using?
Another potential source of an issue is the XLbusParams
type. The API shows that's a union with an int
type and 32 bytes of data. If you have not properly mapped the union (at least the largest member) that could also cause an offset.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论