可以将打包的C结构和函数移植到java吗?

时间:2017-04-12 11:11:37

标签: java c android-studio

过去我编写了处理来自串口的传入数据的代码。数据具有固定格式。 现在我想将此代码迁移到java(android)。但是,我看到了许多障碍。

实际代码更复杂,但我在这里有一个简化版本:

#define byte unsigned char
#define word unsigned short

#pragma pack(1);
struct addr_t
{
  byte foo;
  word bar;
};
#pragma pack();


bool RxData( byte val )
{
  static byte buffer[20];
  static int  idx = 0;

  buffer[idx++] = val;

  return ( idx == sizeof(addr_t) );
}  

每次收到一个字节时都会调用RxData函数。当完整的数据块出现时,它返回true。

一些障碍:

java使用的数据类型不可用。在其他线程中,建议使用更大的数据类型,但在这种情况下,这不是一个可行的解决方案。

在这种情况下,结构的大小正好是3个字节。这也是#pragma声明很重要的原因。否则,C编译器可能会优化"它用于内存使用,因此具有不同的大小。

Java也没有sizeof功能,我找不到这种情况的替代方案。

我可以替换' sizeof'固定值为3,但IMO的做法非常糟糕。

是否可以在java中编写这样的代码?或者尝试将原生c源添加到Android Studio中更明智吗?

1 个答案:

答案 0 :(得分:0)

您的C代码也存在问题。从技术上讲,您不知道charshort有多大。您可能分别需要uint8_tuint16_t。另外,我不确定便携包装是怎样的。

在Java中,您需要一个类。该类可能还会告诉您初始化它需要多少字节。

class Addr
{
    private byte foo;
    private short bar;
    public final static int bufferBytes = 3;

    public int getUnsignedFoo()
    {
        return (int)foo & 0xff;
    }
    public int getUnsignedBar()
    {
        return (int)bar & 0xffff;
    }
}

虽然标准库中可能已经有一个合适的类,但也可能是缓冲区的类。

class Buffer
{
    private final static int maxSize = 20;

    private byte[] bytes = new byte[maxSize];
    private int idx = 0;
    private bool rxData(byte b)
    {
        bytes[idx++] = b;
        return idx == Addr.bufferBytes;
    }
}

要回答关于3的硬编码的问题,这实际上是更好的方法,因为你的协议规范应该说"一个字节用于foo,两个字节用于bar"不是"一个带有char和一个短片的压缩C结构"。反序列化缓冲区的一种方法是这样的:

 public class Addr
 {
     // All the stuff from above
     public Addr(byte[] buffer)
     {
         foo = buffer[0];
         bar = someFunctionThatGetsTheEndiannessRight(buffer[1], buffer[2]);
     }
 }
TI已经离开了故意模糊计算的方式,因为它取决于您的平台和任何事情。你可以简单地用位移来做到这一点,例如

    (((short)buffer[1] & 0xff) << 8) | ((short)buffer[2] & 0xff)

但是,有更好的选择。例如,你可以使用java.nio.ByteBuffer来处理endian isssues。