Serialize openDDS topic to a `std::string`

289 views Asked by At

I've using OpenDDS in a project. Now, for interoperability, we need to send topics also with a custom framework to other machines. Since this custom framework allows to send strings, I'd like to serialize the topics in a string and then send them.

I was using boost::serialization, but then I've made up the idea that in order to send a topic, OpenDDS should be able to serialize a topic some way, so I should be able to pick the corresponding function and use it for serialize data.

Inspecting the code I was able to find the overload of >>= and <<= operators:

void
operator<<= (
    ::CORBA::Any &_tao_any,
    BasicType::LocalForceDataDataReader_ptr _tao_elem)
{
  BasicType::LocalForceDataDataReader_ptr _tao_objptr =
    BasicType::LocalForceDataDataReader::_duplicate (_tao_elem);
  _tao_any <<= &_tao_objptr;
}

/// Non-copying insertion.
void
operator<<= (
    ::CORBA::Any &_tao_any,
    BasicType::LocalForceDataDataReader_ptr *_tao_elem)
{
  TAO::Any_Impl_T<BasicType::LocalForceDataDataReader>::insert (
      _tao_any,
      BasicType::LocalForceDataDataReader::_tao_any_destructor,
      BasicType::_tc_LocalForceDataDataReader,
      *_tao_elem);
}

It serializes the topic into Corba::Any. It seems to work, but now I need to send the content of Corba::Any. Is there a way to put the content of Corba::Any to a string, and retrieve its data from a string? Or, in other words, how can I serialize and deserialize Corba::Any?

Or there's a better way to serialize a OpenDDS topic to a string?

1

There are 1 answers

0
Fred Hornsey On BEST ANSWER

It's possible to use TAO's serialization system to do this, but it's probably better to use what OpenDDS is using: https://github.com/objectcomputing/OpenDDS/blob/master/dds/DCPS/Serializer.h (or at least it's easier for me to write an example for since I know it much better)

These are some functions that will serialize types to and from std::strings:

const OpenDDS::DCPS::Encoding encoding(OpenDDS::DCPS::Encoding::KIND_XCDR2);

template <typename IdlType>
std::string serialize_to_string(const IdlType& idl_value)
{
  const size_t xcdr_size = OpenDDS::DCPS::serialized_size(encoding, idl_value);
  ACE_Message_Block mb(xcdr_size);
  OpenDDS::DCPS::Serializer serializer(&mb, encoding);
  if (!(serializer << idl_value)) {
    throw std::runtime_error("failed to serialize");
  }
  return std::string(mb.base(), mb.length());
}

template <typename IdlType>
IdlType deserialize_from_string(const std::string& xcdr)
{
  ACE_Message_Block mb(xcdr.size());
  mb.copy(xcdr.c_str(), xcdr.size());
  OpenDDS::DCPS::Serializer serializer(&mb, encoding);
  IdlType idl_value;
  if (!(serializer >> idl_value)) {
    throw std::runtime_error("failed to deserialize");
  }
  return idl_value;
}

Also be careful when using std::string for any binary data like CDR to make sure it's not interpreted as a null-terminated string.