2011-04-10 49 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的代碼頂部實現該選項。

相關問題