JNA结构体内存分配数组不正确。

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

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.

huangapple
  • 本文由 发表于 2020年9月10日 21:49:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/63831132.html
匿名

发表评论

匿名网友

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

确定