C++ 将任何数据类型打包到vector<;uint8_t>;

C++ 将任何数据类型打包到vector<;uint8_t>;,c++,vector,stdstring,C++,Vector,Stdstring,这个问题类似于 模板 内嵌无效包(标准::向量&dst、t和数据){ uint8_t*src=静态强制转换(静态强制转换(&data)); dst.insert(dst.end(),src,src+sizeof(T)); } 拆开 template <typename T> inline void unpack (vector <uint8_t >& src, int index, T& data) { copy (&src[index

这个问题类似于

模板
内嵌无效包(标准::向量&dst、t和数据){
uint8_t*src=静态强制转换(静态强制转换(&data));
dst.insert(dst.end(),src,src+sizeof(T));
}
拆开

template <typename T>
inline void unpack (vector <uint8_t >& src, int index, T& data) {
    copy (&src[index], &src[index + sizeof (T)], &data);
}
模板
内联void解包(向量和src、整数索引、T和数据){
复制(&src[索引],&src[索引+大小(T)],&data);
}
我试图将任何类型的数据打包到字节数组中

问题1:我使用uint8_t*实现了现有的繁琐程序,我希望向量的选择是最好的

问题2:我无法使用上述函数正确打包std::string。请让我知道上述功能在打包所有类型的数据类型时有多舒服

请让我知道如何将std::string转换为上述解决方案i e pack和std::string转换为vector

我要打包的数据类型:

所有豆荚 字符串 向量本身

外部问题:

我想把这样的类打包成一个字节数组

class StartPeerSessionRequest : public Request {

public:
    StartPeerSessionRequest();
    virtual ~StartPeerSessionRequest();
    void composeRequestwithHardCodeValues();
    vector<uint8_t> packRequestWithTemplate();

private:
    uint16_t    mProtocolVersion;
    uint16_t    mSessionFlags;
    uint16_t    mMaxResponseLength;
    string      mMake;
    string      mModel;
    string      mSerialNumber;
    uint8_t     mTrackDelay;
    string      mHeadUnitModel;
    string      mCarModelYear;
    string      mVin;
    uint16_t    mVehicleMileage;
    uint8_t     mShoutFormat;
    uint8_t     mNotificationInterval;

};

class Message {

public:
    Message();
    virtual ~Message();
    void composeMessage(vector<uint8_t> data, uint16_t opcode, uint16_t lengthOfData);

    uint16_t packetheader;
    uint16_t length;
    uint16_t request_response_id;
    uint16_t opcode;
    uint16_t checksum;
    vector<uint8_t> data;
}
class StartPeerSessionRequest:公共请求{
公众:
StartPeerSessionRequest();
虚拟~StartPeerSessionRequest();
void composeRequestwithHardCodeValues();
向量packRequestWithTemplate();
私人:
uint16旋转溶出;
uint16_t mSessionFlags;
uint16_t mmax响应长度;
串制;
字符串模型;
字符串mSerialNumber;
uint8_t跟踪延迟;
字符串模型;
字符串mCarModelYear;
字符串mVin;
uint16车辆里程;
uint8_t mShoutFormat;
uint8\u t通知间期;
};
类消息{
公众:
消息();
虚拟~Message();
无效复合信息(矢量数据、uint16操作码、uint16长度数据);
uint16_t包装头;
uint16_t长度;
uint16请求\响应\ id;
uint16操作码;
uint16_t校验和;
矢量数据;
}
我选择的字节数组数据类型是向量(uint8\t)


我想将其写入设备文件或通过蓝牙网络发送。我不想反序列化同一个类。我将收到一个同样是字节数组的响应,我需要最终将响应解压缩到另一个类

tl;dr:使用序列化库,如或

Ad 1)向量正常编辑:但流式处理会更好。

Ad 2)好吧,你不能用这种方式序列化对象,因为你只能得到指向实际数据的指针,而不是数据本身。并且只能序列化()对象;或者更确切地说,不能保证反序列化不是纯旧数据/标准布局的对象将导致工作对象
std::string
(或任何其他容器)不是POD,并且包含间接寻址(
std::string
只是一种特殊的向量)

没有特殊支持,无法将任意非标准布局对象序列化/打包到字节数组。要么您必须为每种类型编写序列化和反序列化函数,要么您必须放弃字节数组要求,并使用类似的方法来维护类型信息,并在幕后为您正确调用构造函数和析构函数。请注意,
boost::any
本身是一个具有间接寻址的非标准布局对象

广告编辑:

我不想反序列化同一个类

是的,你知道。在连接的另一端。所以

  • 另一端使用相同的结构,您必须同时编写序列化和反序列化,一端使用一个,另一端使用另一个
  • 另一端使用不同的结构(甚至可能使用不同的语言),您在这两方面都工作,因此您必须编写匹配的序列化和反序列化,或者
  • 另一端由其他人编写,您必须编写序列化以使用特定的约定格式
  • 有数千种方法可以序列化每种类型。一个字符串可以序列化为长度和内容,或者使用指定的终止符(通常为0字节)终止内容,一个整数(字符串大小为整数)可以序列化为不同的固定字节数,顺序不同(endian),使用可变长度编码等

    然后是变化。我知道你有一个协议版本。但是,您还必须编写反序列化代码,以便根据版本执行不同的操作,这通常意味着无论如何都要逐个成员地执行(您希望独立于版本输出相同的结构,以保持下游代码正常)等等

    如果您还没有确定协议,我建议您查看和库

    • BooSt.序列化很好地覆盖了现有对象,但具体到C++,只提供向后兼容性,即如果发送方发送版本2和接收方没有更新,消息根本就不会被理解。 协议缓冲区需要定义它的特殊格式的消息并从中生成C++定义,但是大多数语言都有生成器,它支持前向兼容性,即如果发送方发送第2版,接收方将理解已经在版本1中的所有字段,而忽略那些没有的版本。

    如果出于某种原因您不能使用它们(除非目标非常有限,否则您应该能够使用;我使用的移动应用程序同时使用Boost和Protobuf,并在当前所有主要移动平台上运行),至少阅读他们的技术说明,并可能查看代码,以便了解如何做好序列化工作。

    tl;dr:使用序列化库,如或

    Ad 1)向量正常编辑:但流式处理会更好。

    Ad 2)好吧,你不能用这种方式序列化对象,
    class StartPeerSessionRequest : public Request {
    
    public:
        StartPeerSessionRequest();
        virtual ~StartPeerSessionRequest();
        void composeRequestwithHardCodeValues();
        vector<uint8_t> packRequestWithTemplate();
    
    private:
        uint16_t    mProtocolVersion;
        uint16_t    mSessionFlags;
        uint16_t    mMaxResponseLength;
        string      mMake;
        string      mModel;
        string      mSerialNumber;
        uint8_t     mTrackDelay;
        string      mHeadUnitModel;
        string      mCarModelYear;
        string      mVin;
        uint16_t    mVehicleMileage;
        uint8_t     mShoutFormat;
        uint8_t     mNotificationInterval;
    
    };
    
    class Message {
    
    public:
        Message();
        virtual ~Message();
        void composeMessage(vector<uint8_t> data, uint16_t opcode, uint16_t lengthOfData);
    
        uint16_t packetheader;
        uint16_t length;
        uint16_t request_response_id;
        uint16_t opcode;
        uint16_t checksum;
        vector<uint8_t> data;
    }