过去我编写了处理来自串口的传入数据的代码。数据具有固定格式。 现在我想将此代码迁移到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中更明智吗?
答案 0 :(得分:0)
您的C代码也存在问题。从技术上讲,您不知道char
和short
有多大。您可能分别需要uint8_t
和uint16_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。