java - 在 Java 中访问的 C 结构

标签 java c cross-platform struct

我有一个 C 结构,它通过一些中间网络发送,并由 Java 代码通过串行链接接收。 Java 代码给了我一个字节数组,我现在想将它重新打包为原始结构。现在,如果接收代码是用 C 编写的,这很简单。有什么简单的方法可以将 java 中的 byte[] 重新打包为 C 结构。我在 Java 方面的经验很少,但这似乎不是一个常见问题,也没有在我能找到的任何常见问题解答中解决。

仅供引用,C 结构是

struct data {
     uint8_t        moteID;
    uint8_t     status; //block or not
    uint16_t   tc_1;
    uint16_t   tc_2;
    uint16_t   panelTemp;  //board temp
    uint16_t   epoch#;
    uint16_t   count;    //pkt seq since the start of epoch
    uint16_t   TEG_v;   
    int16_t   TEG_c;    
 }data;

最佳答案

我建议您始终以网络字节顺序通过线路发送数字。这消除了以下问题:

  1. 为您的结构生成特定于编译器的字边界。
  2. 特定于您的硬件的字节顺序(发送和接收)。

此外,无论您在哪个平台上运行 Java,Java 的数字始终以网络字节顺序存储(JVM 规范需要特定的字节顺序)。

java.nio.ByteBuffer 是一个非常好的从流中提取位的类,它可以包装任意字节数组;不仅仅是来自 java.nio 中 I/O 类的那些。如果可能的话,你真的不应该手动编写你自己的原始值提取代码(即位移等),因为很容易出错,代码对于相同类型的每个实例都是相同的,并且有很多为您提供此功能的标准类。

例如:

public class Data {

    private byte moteId;
    private byte status;
    private short tc_1;
    private short tc_2;
    //...etc...
    private int tc_2_as_int;

    private Data() {
        // empty
    }

    public static Data createFromBytes(byte[] bytes) throws IOException {
        final Data data = new Data();
        final ByteBuffer buf = ByteBuffer.wrap(bytes);

        // If needed...
        //buf.order(ByteOrder.LITTLE_ENDIAN);

        data.moteId = buf.get();
        data.status = buf.get();
        data.tc_1 = buf.getShort();
        data.tc_2 = buf.getShort();
        // ...extract other fields here

        // Example to convert unsigned short to a positive int
        data.tc_2_as_int = buf.getShort() & 0xffff;

        return data;        
    }

}

现在,要创建一个,只需调用 Data.createFromBytes(byteArray)

请注意,Java 没有无符号整数变量,但这些变量将以完全相同的位模式检索。所以任何没有设置高位的东西在使用时都是一样的。如果您希望在无符号数中使用高位,则需要处理高位。有时这意味着将值存储在下一个更大的整数类型中(byte -> short;short -> int;int -> long)。

编辑:更新示例以显示如何将 short(16 位有符号)转换为具有无符号值的 int(32 位有符号)tc_2_as_int

另请注意,如果您不能更改字节顺序并且它不是网络顺序,那么 java.nio.ByteBuffer 仍然可以在这里为您提供 buf.order(ByteOrder. LITTLE_ENDIAN); 在检索值之前。

关于java - 在 Java 中访问的 C 结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2151960/

相关文章:

c - 在 C 程序的 main() 函数中是否有充分的理由将变量声明为静态?

javascript - 每个平台上的 XML、PDF 和 Office 文档的数字签名

c++ - 跨平台错误信息

Java - 从 MAP!s 上的 HASHMAP 中删除最后一个已知项目

java - 如何克隆循环链表

java - 运行 JAR 时为 "java.lang.ClassNotFoundException: javax.ejb.EJBObject"

c - VS2012项目+openssl(LNK2001)

c++ - 找不到我的错误!错误 : expected identifier before '(' token

C++ 什么是更糟糕的抽象或转换?

java - 加载应用程序时出错