我目前正在为 RF24Mesh 微控制器层编写一个抽象层来实现消息签名。
由于我想使其尽可能通用,因此我很想为例如传递任何结构/有效负载成为可能:(这只是一个应该能够传递给函数的结构的示例)
struct payload_sensor {
uint8_t some_other_sensor_data[32];
int sensor_id;
int sensor_data;
};
到签名函数,然后让它处理存储有效负载/结构,直到完成所有其他操作以发送它。
但事情是这样的,我无法预测传递给函数的结构的确切大小(它应该处理传递给它的任何结构),相同的结构可能会被重用(填充其他数据)并再次传递给函数。我完全想不出一个好的解决方案。
现在,我如何实现适当的缓冲区来存储这些未知的有效负载/结构,直到它们准备好发送?我还必须记住,代码是在 AVR 上运行的,因此 AVR 内存(碎片)可能会成为一个问题。
我对结构和更高级的东西有点陌生,所以请不要介意我错过一些明显的东西。
通常,此类问题可以通过定义结构来解决,例如:
struct payload_sensor {
unsigned int struct_size;
int sensor_id;
type any_other_always_present_data;
char variable_data[];
};
其中variable_data
是有效负载的未知部分。
当您知道实际variable_data
需要多大时,您可以执行以下操作:
unsigned int actual_length = length_of_variable_data + sizeof(struct payload_sensor);
struct payload_sensor *myStruct = malloc(actual_length);
myStruct->struct_size = actual_length;
要将变量数据复制到结构中,您将:
memcpy(&myStruct->variable_data, &data_source, length_of_variable_data);
根据评论和编辑,听起来您的意图是能够将数据传递给某个函数,该函数必须保留数据的副本,直到稍后某个时间点,并且该函数不知道它被要求保留的内容。如果是这种情况,您需要做的就是告诉函数每次调用的长度。例如,void myFunction(const void *buffer, unsigned int length);
:
myFunction(&myStructOfType1, sizeof(myStructOfType1));
myFunction(&myStructOfType2, sizeof(myStructOfType2));
并且,基于您对重用结构的担忧,myFunction()
从buffer
开始复制到存储内容的任何位置(以及记录它在副本地址存储的长度)length
字节以供将来处理。
C 中没有"未知大小的结构"这样的东西。 sizeof(payload_sensor)
每次的大小都相同。
char[]
缓冲区传递到具有任何结构memcpy
的函数中。这摆脱了基于结构问题的函数签名。
让按照约定传递的所有结构的第一个结构字节/短/整数持有一个标签,告诉另一端出现什么类型。
如果消息是通过线路(例如UART)发送的,请注意平台之间的字节顺序和不同的sizeof()
问题,这些问题可能会使您的协议基于结构进行叶片尝试。
如果您要交换跨平台消息(例如,在PC和AVR之间),则实际上不想处理编译器的不兼容性。在这种情况下,定义并记录不基于 C 结构的线路协议,并将字节手动放在 unsigned char
缓冲区中它们所属的位置。或者使用基于 ASCII 的协议。