使用预处理器生成消息类型
Generating message type with preprocessor
我想在两个微控制器之间创建一个通信协议,我使用在系统之间合并消息类型的类逻辑。我想通过做一些非常简单的事情来开发一个更简单的创建新消息的过程,例如以下
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中创建高度可移植的简单消息生成器框架。
相关文章:
- 设计帮助 - 为不同类型的消息处理通用接口的设计模式
- glDrawElements GL 错误类型 = 0x824c,严重性 = 0x9146,消息 = GL_INVALID
- 从 Any 包中提取和匹配 protobuf 消息类型名的首选方法
- 如何在不违反类型别名规则的情况下解释消息负载?
- 当模板返回类型阻止其实例化时,如何向用户提供漂亮的static_assert消息?
- 使用预处理器生成消息类型
- 从模板实例化/类型推断中查找错误消息的实际来源
- 错误消息:不允许抽象类类型 "X" 的对象:纯虚拟"Y"没有覆盖器
- 如何从Google Proto Buf消息中的属性名称中找到消息类型
- 如何处理许多不同的输入二进制消息类型
- 为什么我在 gdb 中收到 ifstream 对象的<不完整类型>消息?
- 如何处理多个源队列消息类型
- 异常是否应具有标志/消息,或者每个错误应具有异常类型
- ERRC::timed_out 类型的升压系统make_error_code具有"Unkown error"消息
- 如何在嵌入式 Python 脚本的错误消息中打印 PyObject 的类型
- 此错误消息是否正确:非类型模板参数不是常量表达式
- 如何获取/实现类的内置类型成员变量"Uninitialized uses warning"消息?
- winsock,面向消息的网络,以及从recv中类型转换缓冲区
- 其中列出了gstreamer总线消息类型
- 是否可以在googleprotobuf中为类型(枚举或消息)定义一个别名