4

在我正在開發的嵌入式應用程序中,我經常需要打包來自多個不同對象的數據,以通過串行端口發送出去。同樣,串行端口上的數據需要寫入多個不同的對象。優雅的面向對象的成員訪問沒有大量的獲取/增變器

出於兼容性的原因,在包中的數據的排序不允許與一個對象相關聯的所有數據將被在所述分組連續放置。所以我不能輕鬆地將每個對象的數據等矢量化,然後將所有這些數據放入數據包中。

我可以使用非常大的數量的吸氣劑/增變器的該分組類使用來創建/解碼發送/接收的數據包實現適當的功能性。但這看起來不太優雅。

我可以做包類是拉班的朋友自/至/寫數據,但我總是告訴避免使用朋友,那種違反面向對象原則。

理想的是處理實際應用程序的類不會知道分組分類任何東西(而不是必須提供的getter /存取器專門爲它),而且如果數據包更新之間排在簡單地將有新的數據。

我想,也許我可以在啓動時通過引用或指針相關的成員變量添加到包類,但也棘手,因爲所有的成員都是不一樣的尺寸。也許我也可以傳遞尺寸信息?有沒有辦法將void指針的列表向量化爲成員和成員對的大小,以便包類不需要爲其構造函數提供大量的參數?

我不知道我有多好已經說明這個問題,但我肯定可以提供澄清和詳細信息,如果這將有助於。非常感謝任何想法。

當前TX包類

縮寫示例:

class PacketTx { 
private: 
    uint8_t buffer[MAX_PACKET_SIZE]; // MAX_PACKET_SIZE is 200 
public: 
    PacketTx(object1 *firstObject, 
      object2 *secondObject, 
      object3 *thirdObject 
      // ...etc... 
      ) 

    void sendPacket(void); 
}; 

void PacketTx::sendPacket(void) { 
    uint32_t i = 0; 

    int16_t tempVar1 = firstObject->getVar1(); 
    uint32_t tempVar2 = secondObject->getVar2(); 
    uint8_t tempVar3 = firstObject->getVar3(); 
    int32_t tempVar4 = thirdObject->getVar4(); 
    // ...etc... 

    memcpy(buffer + i, &tempVar1, sizeof(tempVar1)); 
    i += sizeof(tempVar1); 

    memcpy(buffer + i, &tempVar2, sizeof(tempVar2)); 
    i += sizeof(tempVar2); 

    memcpy(buffer + i, &tempVar3, sizeof(tempVar3)); 
    i += sizeof(tempVar3); 

    memcpy(buffer + i), &tempVar4, sizeof(tempVar4)); 
    i += sizeof(tempVar4); 

    // ...etc... 

    for(uint32_t j = 0; j < i; ++j) 
    putc(static_cast<char>(buffer[i])); 
} 

這個例子不包括頭,校驗和等,但它應該給什麼導致我頭疼的一個基本理念。

+0

我認爲這樣做會教對象本身寫入緩衝區的方式OO。 – Wug

+0

這是我以前做這件事的方式。不幸的是,因爲我已經擴展了數據包但仍需要向後兼容,所以對象不能將所有相關的成員變量寫入緩衝區,因爲數據不會位於最終數據包中的連續位置。 – llakais

+0

什麼是「非常大的數字」?未來會增加嗎?你正在處理的數據類型是什麼?它們是異構的嗎?你在尋找什麼樣的表現? –

回答

2

所以如果我知道你有哪些有哪些需要編寫出到緩衝區中以任意順序成員任意數量的一些C類。然後相反的機制發生。

串行 - > Packet.buffer() - >對象(和反向)

我最初的想法是使用boost::tuple和具有該類型對應於在分組中的數據的順序。 (但有可能是50多個成員組成/元組條目可能是一個大編譯時命中)

tuple<float, int, std::string> a(1.0f, 2, std::string("Some Words"); 
ostr << a; 

這也需要您的類以一個元組作爲參數,並填寫項來自數據。因此,而不是寫一個緩衝區有可能是在元組舉行領域的枚舉,使「好」的代碼可以寫爲:

enum Fields {Price,Amount,Reason}; 
typedef boost::tuple<...> MyTuple; 

void MyClass::getData(MyTuple& t) 
{ 
    t<Price>() = mPrice; 
    t<Amount>() = mAmount; 
    t<Reason>() = mSomeReason; 
} 

注意就會逆正常工作。

不確定這是否完全符合您正在嘗試做的事情,但它可能會引發一些新的想法?

+0

非常感謝。我認爲那肯定會奏效。這絕對是一個非常大的元組,但它肯定比我現在做的要好。 – llakais

+0

不知道我會實際執行這個,但它可能是這樣一個惱人的問題最好的答案之一。非常感謝。 – llakais

+0

np - 我喜歡這個問題:) – Caribou

1

成分是你需要在這裏什麼:

class packet { 
    enum PacketType { 
     type1, 
     ... 
    }; 
    std::vector<unsigned char> buffer; 
    PacketType id; 
public: 
    void setData(std::vector<unsigned char> buffer); 
    void setType(PacketType type); 
    std::vector<usigned char> getData(); 
    PacketType getType(); 
    //serialize Packet; 
}; 

class composition_packet { 
    //other packet related detail. 
    std::vector<packet> data; 
public: 
    void addPacket(packet p); 
    void send(); 
    //serialize composition_packet 
}; 

這裏的想法是讓儘可能需要多個數據包,但把他們作爲一個大包(composition_packet)。這裏的另一個概念是數據包只負責序列化自己,而不是應該知道的數據類型。數據包必須已經被一個知道如何序列化的對象序列化。


struct foo { 
    std::string str; 
    uint_8 u8; 
    uint_32 u32; 

    packet getPacket() { 
     //simple dumb serialization 
     std::stringstream ss(str); 
     ss << "|"; //delimit character 
     ss << u8 << "|"; 
     ss << u32; 
     std::string s(ss.str()); 
     std::vector<unsigned char> data(s.begin(), s.end()); 
     packet p; 
     p.setType(packet::fooType); 
     p.setData(data); 
     return p; 
    } 

}; 
+0

問題是,從字面上看沒有合理的方法將數據包解析爲多個較小的數據包。考慮來自多個不同尺寸的隨機對象的隨機數據。我不確定讓對象序列化數據本身是有意義的,因爲數據在數據包中不會連續。 – llakais

+0

***「數據包中不會連續出現」*** 我不確定你的意思是?我將舉一個例子用例。你能指出這個問題嗎? – andre

+0

在這種情況下,例如,u8和u32不能保證在合成包中彼此相鄰。最終數據包中的數據順序(通過串行端口實際發送的數據)非常重要,因爲現在系統具有向後兼容性。即如果A和B必須相互通話,那麼即使A具有舊代碼,只要添加到B的tx流的新數據僅在最後加上,A仍然可以從B接收數據。如果A和B具有相同的轉碼(即A期望增加的數據),但至少系統仍然有效,則不會獲得新功能。 – llakais

相關問題