Boost:序列化/反序列化通过ZeroMQ拉套接字传递的自定义C ++对象 [英] Boost: Serializing/De-serializing a custom C++ object passed over ZeroMQ pull socket

查看:671
本文介绍了Boost:序列化/反序列化通过ZeroMQ拉套接字传递的自定义C ++对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说明:



我有一个名为 GenericMessage 的C ++类,它只保存ID和数据成员(见下面的代码片段1 - GenericMessage.hxx)。我的目的是序列化这个类的实例,并通过实现推式模式的ZeroMQ套接字发送它。



序列化和发送任务已在类ZMQHandler (请参阅sendToBE函数)中实现,它放在头文件名ZMQHandler.hxx中在下面的代码段2 中。此类通过第三个代码段中显示的 TestFE.cxx 实例化。



GenericMessage实例的序列化在第四个代码段中提供的 TestBE.cxx 中实现。我的意图是通过ZMQ套接字接收GenericMessage实例(即pull socket),解序列化它然后打印它的成员。



问题:当我编译TestBE.cxx时,我有一些涉及模板函数的编译错误。考虑到TestBE.cxx中的代码,任何人都可以告诉我在第4个代码片段中标记有注释的反序列化部分中缺少什么?我相对是一个新的C ++程序员,想知道我应该如何解释这些模板函数相关的编译错误已经列在本文的底部(即最后的代码段)。导致编译错误的第18行标记在第4个代码段中。感谢。



CODE SNIPPET 1(GenericMessage.hxx)

  #include< iostream> 
#include< string>
#include< sstream>
#include< boost / serialization / serialization.hpp>
#include< boost / archive / binary_oarchive.hpp>
#include< boost / archive / binary_iarchive.hpp>
#include< boost / archive / text_oarchive.hpp>
#include< boost / archive / text_iarchive.hpp>

template< class T>
class GenericMessage {
public:
GenericMessage():
beId(-1),data(NULL)
{}

GenericMessage (int id,T msg):beId(id),data(msg)
{}

〜GenericMessage(){}

T getData b $ b {
返回数据;
}


std :: string toString()
{
std :: ostringstream ss;
ss<< getBeId();
std :: string ret = ss.str();

return ret;
}

void setBeId(int id)
{
beId = id;
}

int getBeId()
{
return beId;
}


private:
friend class boost :: serialization :: access;

int beId;
T data;

template< class Archieve>
void serialize(Archieve& ar,const unsigned int version)
{
ar& beId;
ar&数据;
}

};

CODE SNIPPET 2(ZMQHandler.hxx)
$ b

  #includezmq.hpp
#includeGenericMessage.hxx
#include< pthread.h>
#include< unistd.h>
#include< cassert>

template< class A>
class ZmqHandler {
public:

ZmqHandler():
mContext(1),
mOutbHandlerSocket(mContext,ZMQ_PUSH)
{
mOutbHandlerSocket.bind(tcp:// *:5555);
}

〜ZmqHandler(){}

void sendToBE(GenericMessage< A& theMsg)
{
std :: stringstream ss(std :: ios_base :: binary | std :: ios_base :: out | std :: ios_base :: in);
boost :: archive :: binary_oarchive oa(ss,boost :: archive :: no_header);
oa<< theMsg;

zmq :: message_t msgToSend(sizeof(ss));

memcpy(msgToSend.data(),ss.str()。data(),ss.str()。length());
if(memcmp(msgToSend.data(),ss.str()。data(),ss.str()。length())!= 0)
{
printf memcpy error\\\
);
}

mOutbHandlerSocket.send(msgToSend);
std :: cout<< SENT request:[<< theMsg.toString()<< ]<< std :: endl;
}

private:
zmq :: context_t mContext;
zmq :: socket_t mOutbHandlerSocket;
};

CODE SNIPPET 3(TestFE.cxx)
$ b

  #includeZmqHandler.hxx

int main()
{
ZmqHandler< std: :string> zmqHandler;
int counter = 1;

while(1)
{
std :: string data =Hello there!\0
GenericMessage< std :: string> msg(counter,data);
zmqHandler.sendToBE(msg);
counter ++;
sleep(1);
}

return 0;
}

CODE SNIPPET 4(TestBE.cxx) / p>

  #includezmq.hpp
#includeGenericMessage.hxx
#include< fstream> ;

int main()
{
//准备我们的上下文和套接字
zmq :: context_t context(1);
zmq :: socket_t socket(context,ZMQ_PULL);

std :: cout<< 连接到FE ...< std :: endl;
socket.connect(tcp:// localhost:5555);

while(1){
zmq :: message_t reply;
socket.recv(& reply);

/ * !!!!!!! LINE 18从这里开始!!!!!!! * /
std :: stringstream is(reply.data(),std :: ios_base :: binary | std :: ios_base :: out | std :: ios_base :: in);
boost :: archive :: binary_iarchive ia(is,boost :: archive :: no_header);

GenericMessage< std :: string> msg;
ia>> msg;

std :: cout<< RECEIVED:<< msg.toString()<< std :: endl;
std :: cout<< DATA:<< ((std :: string)msg.getData())< std :: endl;
}

return 0;
}

TestBE.cxx的编译OUTPUT

  g ++ -g -c TestBE.cxx GenericMessage.hxx 
TestBE.cxx:在函数'int main()':
TestBE.cxx:18:104:error:无效的用户定义从'void *'转换为'const __string_type& {aka const std :: basic_string< char>&}'[-fpermissive]
在/usr/include/c++/4.7/string:55:0包含的文件中,
从/ usr / include /c++/4.7/bits/locale_classes.h:42,
来自/usr/include/c++/4.7/bits/ios_base.h:43,
来自/usr/include/c++/4.7/ios :43,
从/usr/include/c++/4.7/ostream:40,
从/usr/include/c++/4.7/iostream:40,
从GenericMessage.hxx:1,
从TestBE.cxx:2:
/usr/include/c++/4.7/bits/basic_string.tcc:214:5:注意:候选是:std :: basic_string< _CharT,_Traits,_Alloc> :: basic_string(const _CharT *,const _Alloc&)[with _CharT = char; _Traits = std :: char_traits< char> ;; _Alloc = std :: allocator< char>]< near match>
/usr/include/c++/4.7/bits/basic_string.tcc:214:5:注意:没有已知的从'void *'到'const char *'的参数1的转换
TestBE.cxx: 18:104:错误:从'void *'到'const char *'的无效转换[-fpermissive]
在包含在/usr/include/c++/4.7/string:55:0,
从/usr/include/c++/4.7/bits/locale_classes.h:42,
从/usr/include/c++/4.7/bits/ios_base.h:43,
从/ usr / include / c ++ / 4.7 / ios:43,
来自/usr/include/c++/4.7/ostream:40,
来自/usr/include/c++/4.7/iostream:40,
来自GenericMessage .hxx:1,
从TestBE.cxx:2:
/usr/include/c++/4.7/bits/basic_string.tcc:214:5:error:初始化'std :: basic_string< ; _CharT,_Traits,_Alloc> :: basic_string(const _CharT *,const _Alloc&)[with _CharT = char; _Traits = std :: char_traits< char> ;; _Alloc = std :: allocator< char>]'[-fpermissive]
make:*** [TestBE.o]错误1


解决方案

我会说错误信息很清楚: stringstream 的构造函数需要类型 openmode std :: string ,并且传递了 void * reply.data())的参数。



您可以将收到的邮件转储为二进制文件,但您仍需要进行一些转换。


Description:

I have a C++ class named GenericMessage which simply holds an id and data as its members (See code snippet 1 below - GenericMessage.hxx). My intention is to serialize an instance of this class and send it via a ZeroMQ socket which implements the push pattern.

The serialization and sending task has been implemented in class ZMQHandler (see sendToBE function) which is placed in a header file name ZMQHandler.hxx shown in the code snippet 2 below. This class is instantiated by TestFE.cxx shown in the 3rd code snippet below.

The receiving and de-serialization of the GenericMessage instance is implemented in TestBE.cxx available in the 4th code snippet below. My intentiton is to receive the GenericMessage instance over the ZMQ socket (i.e. pull socket), de-serialize it and then print its members.

Problem:

The problem is that when I compile TestBE.cxx, I am having a number of compilation errors involving template functions. Considering the code in TestBE.cxx, can anyone tell me what I am missing in de-serialization part that is marked with comments in the 4th code snippets? I am relatively a new C++ programmer and wonder how I should interpret these template functions related compilation errors which have been listed at the bottom of this text (i.e. the final snippet). Line 18 where the compilation error originates is marked in the 4th code snippet. Thanks.

CODE SNIPPET 1 (GenericMessage.hxx)

#include <iostream>
#include <string>
#include <sstream>
#include <boost/serialization/serialization.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

template <class T>
class GenericMessage {
public:
      GenericMessage(): 
      beId(-1), data(NULL)
      {}

      GenericMessage(int id, T msg): beId(id), data(msg)
      {}

     ~GenericMessage(){}

     T getData()
     {
       return data;
     }


     std::string toString()
     {
        std::ostringstream ss;
        ss << getBeId();
        std::string ret =  ss.str();

        return ret;
      }

      void setBeId(int id)
      {
        beId = id;
      }

      int getBeId()
      {
        return beId;
      }


      private:
            friend class boost::serialization::access;

            int beId;
            T data;

            template <class Archieve>
            void serialize(Archieve & ar, const unsigned int version)
            {
               ar & beId;
               ar & data;
            }

 };

CODE SNIPPET 2 (ZMQHandler.hxx)

 #include "zmq.hpp"
 #include "GenericMessage.hxx"
 #include <pthread.h>
 #include <unistd.h>
 #include <cassert>

template <class A>
class ZmqHandler {
public:

       ZmqHandler():
   mContext(1),
   mOutbHandlerSocket(mContext, ZMQ_PUSH)
       {    
            mOutbHandlerSocket.bind ("tcp://*:5555");       
       }

       ~ZmqHandler() {}

        void sendToBE(GenericMessage<A> &theMsg)
        {
           std::stringstream ss(std::ios_base::binary| std::ios_base::out|  std::ios_base::in);
           boost::archive::binary_oarchive oa(ss, boost::archive::no_header);
           oa << theMsg;

           zmq::message_t msgToSend(sizeof(ss));

           memcpy(msgToSend.data(), ss.str().data(), ss.str().length());
           if(memcmp(msgToSend.data(), ss.str().data(), ss.str().length()) != 0)
           {
               printf("memcpy error\n");
           }

           mOutbHandlerSocket.send(msgToSend);
           std::cout << "SENT request: [" << theMsg.toString() << "]" << std::endl;
}   

    private:  
          zmq::context_t mContext;
          zmq::socket_t mOutbHandlerSocket;         
};

CODE SNIPPET 3 (TestFE.cxx)

 #include "ZmqHandler.hxx"

 int main ()
 {
   ZmqHandler<std::string> zmqHandler;
   int counter = 1;

   while(1)
   {  
     std::string data = "Hello there!\0";
     GenericMessage<std::string> msg(counter, data);
     zmqHandler.sendToBE(msg);
     counter++;
     sleep(1);
    }

    return 0;
 }     

CODE SNIPPET 4 (TestBE.cxx)

 #include "zmq.hpp"
 #include "GenericMessage.hxx"
 #include <fstream>

 int main ()
 {
    //  Prepare our context and socket
    zmq::context_t context (1);
    zmq::socket_t socket (context, ZMQ_PULL);

   std::cout << "Connecting to FE..." << std::endl;
   socket.connect ("tcp://localhost:5555");

   while(1){
       zmq::message_t reply;
       socket.recv (&reply);

       /* !!!!!!! LINE 18 starts HERE !!!!!!! */
       std::stringstream is(reply.data(), std::ios_base::binary| std::ios_base::out| std::ios_base::in);
       boost::archive::binary_iarchive ia(is, boost::archive::no_header);

       GenericMessage<std::string> msg;
       ia >> msg;

       std::cout << "RECEIVED: " << msg.toString() << std::endl;
       std::cout << "DATA: " << ((std::string)msg.getData())  << std::endl;
    }

     return 0;
 }

Compilation OUTPUT of TestBE.cxx

 g++ -g -c TestBE.cxx GenericMessage.hxx
 TestBE.cxx: In function ‘int main()’:
 TestBE.cxx:18:104: error: invalid user-defined conversion from ‘void*’ to ‘const  __string_type& {aka const std::basic_string<char>&}’ [-fpermissive]
       In file included from /usr/include/c++/4.7/string:55:0,
             from /usr/include/c++/4.7/bits/locale_classes.h:42,
             from /usr/include/c++/4.7/bits/ios_base.h:43,
             from /usr/include/c++/4.7/ios:43,
             from /usr/include/c++/4.7/ostream:40,
             from /usr/include/c++/4.7/iostream:40,
             from GenericMessage.hxx:1,
             from TestBE.cxx:2:
  /usr/include/c++/4.7/bits/basic_string.tcc:214:5: note: candidate is:     std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&)  [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>] <near  match>
  /usr/include/c++/4.7/bits/basic_string.tcc:214:5: note:   no known conversion for argument 1 from ‘void*’ to ‘const char*’
  TestBE.cxx:18:104: error: invalid conversion from ‘void*’ to ‘const char*’ [-fpermissive]
       In file included from /usr/include/c++/4.7/string:55:0,
             from /usr/include/c++/4.7/bits/locale_classes.h:42,
             from /usr/include/c++/4.7/bits/ios_base.h:43,
             from /usr/include/c++/4.7/ios:43,
             from /usr/include/c++/4.7/ostream:40,
             from /usr/include/c++/4.7/iostream:40,
             from GenericMessage.hxx:1,
             from TestBE.cxx:2:
       /usr/include/c++/4.7/bits/basic_string.tcc:214:5: error:   initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ [-fpermissive]
       make: *** [TestBE.o] Error 1

解决方案

I would say the error message is quite clear : the constructor of stringstream needs either type openmode or std::string, and you passed a parameter of type void* (the return of reply.data()).

You could dump received message into a binary file instead, but you'd still need to do some casting.

这篇关于Boost:序列化/反序列化通过ZeroMQ拉套接字传递的自定义C ++对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆