使用预处理器生成消息类型

Generating message type with preprocessor

本文关键字:消息 类型 处理器 预处理      更新时间:2023-10-16

我想在两个微控制器之间创建一个通信协议,我使用在系统之间合并消息类型的类逻辑。我想通过做一些非常简单的事情来开发一个更简单的创建新消息的过程,例如以下

BEGIN_MSG(LinearDriveMsg)
ADD_2BIT(DriveSpeed, speed)
ADD_16BIT(GMath::Position, position.x)
END_MSG

理想情况下,它将扩展到:

BEGIN_MSG(LinearDriveMsg)
BEGIN_SERIALIZER
ADD_SERIALIZER_2BIT(DriveSpeed, speed)
ADD_SERIALIZER_16BIT(GMath::Position, position.x)
END_SERIALIZER
BEGIN_DESERIALIZER
ADD_DESERIALIZER_2BIT(DriveSpeed, speed)
ADD_DESERIALIZER_16BIT(GMath::Position, position.x)
END_DESERIALIZER
END_MSG

然后扩展到 cpp 代码

bool LinearDriveMsg::deserialize(const uint8_t *incoming_buffer, const uint8_t *incoming_size) override{
if (*incoming_size != getMessageSize())
return false;
_speed = (DriveSpeed)((incoming_buffer[0] & SPEED_MASK) >> SPEED_OFFSET);
weldTwoBytesToInt(&incoming_buffer[1], _position.x);
return true;
}
int LinearDriveMsg::serialize(uint8_t *outgoing_buffer, uint8_t *outgoing_size) const override{
if (*outgoing_size < getMessageSize())
return -1;
outgoing_buffer[0] |= ((uint8_t)_speed << SPEED_OFFSET) & SPEED_MASK;
cutIntToTwoBytes(_position.x, outgoing_buffer + 1, 2);
return getMessageSize();
}

我知道做一些高级预处理器的东西非常棘手,但也许有一些方法可以完成这项任务?也可以调整实际的 cpp 代码以使其成为可能(这样效率仍然可以(

我会自己回答。实际上,在预处理器中,有"简单"的方法来解决上述任务。boost库提供了大约在预处理器中工作的工具,就像在普通语言中一样。他们有一个名为预处理器的包,作为 boost 套件的一部分阅读文档,您可以在此处下载它是主包的一部分。

帮助解决上述任务的主要功能是将数组元组转发到我们从函数式编程中知道的构造的想法。其实是BOOST_PP_SEQ_FOR_EACH(macro, data, seq).另一个有助于解决任务的功能是这个家伙的实现,在每个元素周围创建双括号。

作为想法,它将像下面一样工作。我有上面的元组列表:

#define frame_composition (begin_byte(0), begin_bit(0), int8_t, speed)
(begin_byte(1), begin_bit(4), int16_t, direction)

我有某种动作顺序,因为我想先有串行,然后是解序列:

#define COMPOSE_FRAME(seq) 
ADD_SERIAL(seq) 
ADD_DESERIAL(seq)

现在每个添加类别的内容:

#define ADD_SERIAL(seq) 
BOOST_PP_SEQ_FOR_EACH(ADD_SERIAL_ELEM, ~, GLK_PP_SEQ_DOUBLE_PARENS(seq))
#define ADD_DESERIAL(seq) 
BOOST_PP_SEQ_FOR_EACH(ADD_DESERIAL_ELEM, ~, GLK_PP_SEQ_DOUBLE_PARENS(seq)) 

很酷的是,我们将相同的元组列表转发到不同的构造,以执行一些不同的算法。现在,X_ELEM的内容定义了:

#define ADD_SERIAL_ELEM(seq) 
outgoing_buffer[BOOST_PP_TUPLE_ELEM( 0, elem)] = (uint8_t) BOOST_PP_TUPLE_ELEM( 3, elem); 
#define ADD_DESERIAL_ELEM(seq) 
BOOST_PP_TUPLE_ELEM(3,elem) = (BOOST_PP_TUPLE_ELEM(2,elem)) incoming_buffer[BOOST_PP_TUPLE_ELEM(0,elem)];

如果需要,您可以使用元素"函数"区分不同的用例

BOOST_PP_IF(cond, t, f)

做不同的事情,例如在对象和简单变量上

这不是完整的解决方案,但要看到这个想法,并且可以从cpp中创建高度可移植的简单消息生成器框架。