Ускорение: сериализация / десериализация пользовательского объекта C ++, передаваемого через ZeroMQ pull-сокет

Описание:

У меня есть класс C ++ с именем GenericMessage который просто содержит идентификатор и данные в качестве своих членов (см. фрагмент кода 1 ниже — GenericMessage.hxx). Мое намерение состоит в том, чтобы сериализовать экземпляр этого класса и отправить его через сокет ZeroMQ, который реализует шаблон push.

Задача сериализации и отправки была реализована в класс ZMQHandler (см. функцию sendToBE), которая находится в заголовочном файле с именем ZMQHandler.hxx, показанном в фрагмент кода 2 ниже. Этот класс создан TestFE.cxx Показано в третий фрагмент кода ниже.

Получение и десериализация экземпляра GenericMessage реализована в TestBE.cxx доступны в 4-й фрагмент кода ниже. Мое намерение состоит в том, чтобы получить экземпляр GenericMessage через сокет ZMQ (т.е. вытащить сокет), десериализовать его, а затем распечатать его элементы.

Проблема:

Проблема в том, что когда я компилирую TestBE.cxx, у меня возникает ряд ошибок компиляции, связанных с шаблонными функциями. Учитывая код в TestBE.cxx, кто-нибудь может сказать мне, что мне не хватает в части десериализации, которая отмечена комментариями в 4-х фрагментах кода? Я относительно новый программист на C ++ и удивляюсь, как мне следует интерпретировать ошибки компиляции, связанные с этими шаблонными функциями, которые перечислены в нижней части этого текста (то есть в последнем фрагменте). Строка 18, в которой возникает ошибка компиляции, отмечена в 4-м фрагменте кода. Благодарю.

КОД 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;
}

};

КОД 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;
};

КОД 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;
}

КОД 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;
}

ВЫХОД компиляции 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

3

Решение

Я бы сказал, что сообщение об ошибке совершенно ясно: конструктор потока строк нужен либо тип openmode или же std::string, и вы передали параметр типа void* (возвращение reply.data()).

Вместо этого вы можете записать полученное сообщение в двоичный файл, но вам все равно придется выполнить приведение.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]