2011-04-10 68 views
3

我正在为avr芯片编写一个函数,将字节流反序列化为原始类型。我希望尽可能以通用的方式来完成,并想知道确定反序列化类型的最佳实践是什么。想法我到目前为止,包括:在C++函数中传递原始数据类型的最佳做法

选项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 */ } 
}; 

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

+1

当在这里看到大图时,将这些东西放在类似C++'iostream'的界面中,而不是笨重的C风格函数中是不是更好?相同的'模板'方式将是可能的,但语法最终会更容易理解。 – rubenvb 2011-04-10 09:36:56

+0

@rubenvb - 虽然空间有限,我不想靠近iostream的重复,但我喜欢遵循其功能命名和约定的想法。 – baalexander 2011-04-11 03:49:38

+0

为什么这些'for(unsigned int i = 0; i (in))'。 – ndim 2011-04-13 23:41:29

回答

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指定模板参数。

+0

我跟你一起去了,阿莎想通过价值。我喜欢在你的函数中返回偏移量。最终的结果可以在https://github.com/baalexander/avr_bridge/blob/master/scripts/avr_ros/serializer.h看到 – baalexander 2011-04-11 03:43:49

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); 
0

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

1

一个忠告:

使用C++为AVR通常不推荐用于多种原因,和一些事情全力以赴不会在所有的工作 - 所以要小心在测试代码在将任何重要时间投入到任何特定路径之前,您的目标芯片。

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

+0

我不想劫持这个问题,但是你有没有引用C++的存在不适用于AVR?我正在编辑一个在AVR上广泛使用C++的项目(比如Atmega 328P),它似乎很好。我很好奇要看什么。 – baalexander 2011-04-11 03:47:26

0

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

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

请注意,如果您希望选择B的语法,在以后的日期(通过为不同类型提供专业化),始终可以在选择A的代码顶部实现该选项。

相关问题