3

我正在为 avr 芯片编写一个函数,以将字节流反序列化为原始类型。我想以尽可能通用的方式进行操作,并且想知道确定要反序列化的类型的最佳实践是什么。到目前为止,我的想法包括:

选项A:

// Just write a function for each type
double deserialize_double(uint8_t *in) { }

选项 B:

// Use a template, and pass the type in when calling
// Function:
template <typename TYPE>
TYPE deserialize(uint8_t *in) {
  union {
    TYPE real;
    uint8_t base[sizeof(TYPE)];
  } u;

  for (unsigned int i = 0; i < sizeof(TYPE); i++) {
    u.base[i] = in[i];
  }
  return u.real;
}

// Call:
double value = deserialize<double>(in);

选项 C:

// Similar to B, but you pass in the type as a parameter
// Function:
TYPE deserialize(uint8_t *in, TYPE);

// Call:
double value = deserialize(in, double);

选项 D:

// Use a templated class. My main issue with this is I was hoping 
// to re-use the same object for deserializing multiple types.
template <typename TYPE>
class Serializer {
  public void serialize(uint8_t *out, TYPE value) { /* code */ }
  public TYPE deserialize(uint8_t *int) { /* code */ }
};

关于最好的方法的任何想法?也许我忽略了一个更简单的方法。

4

5 回答 5

3

首先,C 和 D 是无效选项,因为类型不是有效的函数参数;不妨现在就将它们排除在外。

假设您不关心字节顺序或其他使用联合的潜在警告,选择 B 似乎是明显的赢家(看起来您不会获得这项工作的上下文)。

要考虑的另一件事是在反序列化时有一些反馈机制来推进字节流指针/索引。也许你可以尝试类似

template <typename TYPE>
int deserialize(uint8_t *in, TYPE& value) {
    union {
        TYPE real;
        uint8_t base[sizeof(TYPE)];
    } u;

    for (unsigned int i = 0; i < sizeof(TYPE); i++) {
        u.base[i] = in[i];
    }
    value = u.real;
    return sizeof(TYPE);
}

// Call:
double foo, bar;
int baz;
in += deserialize(in, foo);   // Implicit double deserialize
in += deserialize(in, bar);   // Implicit double deserialize
in += deserialize(in, baz);   // Implicit int deserialize

这还有一个额外的优势(我看到@Asha 已经打败了我!)允许您利用 C++ 模板的类型推断系统;由于第二个参数在调用位置具有已知类型,因此无需为 TYPE 显式指定模板参数。

于 2011-04-10T05:25:58.020 回答
2

另一种选择是将结果作为“out”参数返回。在这种情况下,您无需在模板实例化期间指定类型。像这样的东西:

template <typename TYPE>
void deserialize(uint8_t *in, TYPE& out) {
  union {
    TYPE real;
    uint8_t base[sizeof(TYPE)];
  } u;

  for (unsigned int i = 0; i < sizeof(TYPE); i++) {
    u.base[i] = in[i];
  }
  out = u.real;
  return;
}

// Call:
double value = 0;
deserialize(in, value);
于 2011-04-10T05:21:40.963 回答
1

提醒一句:

出于多种原因,通常不建议将 C++ 用于 AVR,而且有些事情根本无法正常工作——所以在花费大量时间来处理任何特定问题之前,请小心在目标芯片上测试您的代码小路。

但这并不意味着您必须放弃任何重要的功能。只需调整您的代码以适应可用的语言功能。

于 2011-04-10T05:37:40.573 回答
0

您应该使用选项 A,因为:

  1. 它引入了最小的复杂性。
  2. 与 C 和 C++ 兼容。
  3. 如果不支持该类型,则提供直接的行为。

请注意,如果您需要选项 B 的语法,则始终可以在以后在选项 A 的代码之上实现它(通过为不同类型提供专门化)。

于 2011-04-10T06:17:08.880 回答
0

在我看来,选择 B是最好的。它增加了可读性和易于使用。此外, TYPE 也可以是更大的类/结构吗?因为你是从你的deserialize()方法中按价值返回的!

于 2011-04-10T05:36:12.620 回答