场景
分布式程序,通过MPI发送消息,消息的内容void*, 即可能不是POD,类型中可能包含vector或其它自定义类。
涉及技术
- Iostreams : 可以自定义输入/输出源。输入输出内容自己管理,这样你可以对得到的输出内容做一些操作。
- Serialization : 序列化/反序列化工具,对一个POD或者非POD类序列和反序列化。
- 上述两者的结合使用:将一个自定义的类,序列化后得到的二进制字节内容通过网络发送出去,对方收到内容后反序列化成类。这里涉及到几个问题:1. 将类序列化,利用Serialization可以实现,Serialization序列化的内容输出到std::ostream类中,所以输出可以是文件(ofstream类)、osstrem、字节流、通过Iostreams自定义的输出源。同理,输入内容也是通过istream类取得。2. 要得到序列化的字节内容,并且要清楚知道字节内容的大小,这时候,就必须通过Iostreams自定义的输出源/输入源,这样你可以自定义如何接收内容,你对管理的内容是很清楚的。
样例代码
#include <fstream>
// include headers that implement a archive in simple text format
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
// 自定义类
class gps_position
{
private:
friend class boost::serialization::access;
// Serialization要求提供的方法
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & degrees;
ar & minutes;
ar & seconds;
}
int degrees;
int minutes;
float seconds;
public:
gps_position(){};
gps_position(int d, int m, float s) :
degrees(d), minutes(m), seconds(s){}
};
int main() {
// 序列化内容输出源
std::ofstream ofs("filename");
const gps_position g(35, 59, 24.567f);
// 下面序列化一个实例
{
// 以ofs为输出源,构建oarchive (text_oarchive是其中一种)
boost::archive::text_oarchive oa(ofs);
// 将g实列内容进行序列化,序列化的内容最终会输出到ofs中
oa << g;
// archive and stream closed when destructors are called
}
// 从输入源中反序列化一个实例
gps_position newg;
{
// 输入源
std::ifstream ifs("filename");
// 以ifs为输入源,构建iarchive
boost::archive::text_iarchive ia(ifs);
// 反序列化ifs中内容得到实例newg
ia >> newg;
// archive and stream closed when destructors are called
}
return 0;
}
-
上述,序列化和反序列化内容都是在ofstream和ifstream中,如果我们想要得到序列化的字节数据,通过ofstream显然不行,这是就自定义一个ostream子类,即通过 Iostreams 可以自定义输入输出源,可以管理输入输出的内容。
-
如果对POD类进行序列化和反序列化,其序列化内容是字节内容,可以不用Serialization,因为通过std::memcpy就可以实现。
size_t capacity_ = 10000;
char* data_ = new ValueType[capacity_]();
// 将gps_position是个POD类
gps_position gps;
std::memcpy(data_, reinterpret_cast<char*>(&gps), sizeof(gps));
std::memcpy(reinterpret_cast<char*>(&gps), data_ , sizeof(gps_position));
- 判断是一个类是否是POD: std::is_trivially_copyable<T>::value
// pod调用这个方法
template <typename Msg>
typename std::enable_if<std::is_trivially_copyable<Msg>::value, bool>::type
OutBuffer::Add(Msg& msg) {
}
// 非pod调用这个方法
template <typename Msg>
typename std::enable_if<!std::is_trivially_copyable<Msg>::value, bool>::type
OutBuffer::Add(Msg& msg) {
}
网友评论