What’s New in the Modern C++ API

RTI_dev-357518-edited

Since we introduced the modern C++ API for DDS, we’ve seen a lot of interest from our customers. Several of them have started developing brand new systems in C++11. We’ve also been constantly improving the API and there are a few new features, big and small, that I wanted to talk about here.

Improved IDL mapping to C++. The Code Generator provides a new, enhanced mapping to modern C++. A new option, -stl, combined with -language C++03 or -language C++11 enables it.

This option changes the mapping of the following IDL types:

  • Unbounded sequences map tostd::vector(this requires -unboundedSupport)
  • Bounded sequences map torti::core::bounded_sequence<T, Bound>. This type is similar to a std::vector, but is optimized for data deserialization. If minimizing latency is not a top concern, or T is simple, you can choose to map bounded sequences to std::vector as well with the new @use_vector IDL annotation.
  • Strings and wide strings map tostd::string,andstd::wstringrespectively.
  • Members with the new annotation @external (equivalent to the “*” pointer notation) map to the new typedds::core::external<T>,similar toshared_ptr.This wrapper provides a safer alternative to the previous mapping to a raw pointer. An external member cannot be overwritten when its memory is loaned from the middleware (for example, when reading aLoanedSamplescontainer).

For example, given the following IDL type:

struct MyType {
   sequence<long> my_unbounded_seq;
   sequence<long, 10> my_bounded_seq;
   @use_vector sequence<long, 10> my_other_bounded_seq
   string my_str;
   @external long my_external;
};

This is how the generated C++11 type looks like with “-stl”

(Full command: rtiddsgen -language C++11 -stl -unboundedSupport MyType.idl)

class MyType {

 public:
   MyType();
   ...

   MyType (MyType&&) = default;
   MyType& operator=(MyType&&) = default;
   MyType& operator=(const MyType&) = default;
   MyType(const MyType&) = default;

   std::vector<int32_t>& my_unbounded_seq() noexcept;
   const std::vector<int32_t>& my_unbounded_seq() const noexcept;
   void my_unbounded_seq(const std::vector<int32_t>& value);

   rti::core::bounded_sequence<int32_t, 10>& my_bounded_seq() noexcept;
   const rti::core::bounded_sequence<int32_t, 10>& my_bounded_seq() const noexcept;
   void my_bounded_seq(const rti::core::bounded_sequence<int32_t, 10>& value);

   std::vector<int32_t>& my_other_bounded_seq() noexcept;
   const std::vector<int32_t>& my_other_bounded_seq() const noexcept;
   void my_other_bounded_seq(const std::vector<int32_t>& value);

   std::string& my_str() noexcept;
   const std::string& my_str() const noexcept;
   void my_str(const std::string& value);

   dds::core::external<int32_t>& my_external() noexcept;
   const dds::core::external<int32_t>& my_external() const noexcept;
   void my_external(dds::core::external<int32_t> value);

   ...
};

Request-reply API. The new request-reply API for modern C++ extends the DDS API with two entities: rti::request::Requester and rti::request::Replier. This API was already available in other languages, and is now available in modern C++ as a prototype in 5.3 and production-ready in 5.3.0.7.

A simple code example is availabe here

We’ve made additional small improvements to make the API easier to use. For instance, we simplified how to use handlers for dispatching Conditions in a WaitSet. Previously, handlers had to be no-argument functors. Now they can take the Condition as an argument.

condition.handler([]() { 
// do something
});

// now we also support
condition.handler([](dds::core::cond::Condition c) {
// do something (condition == c)
});

We’ve also kept the API up to date with new connectivity features, such as TopicQuery, which we introduced in 5.3. Topic queries provide a scalable mechanism for applications to receive historical data on-demand.
In the modern C++ API you can create a TopicQuery instance from a DataReader as follows:

rti::sub::TopicQuery my_topic_query(
my_reader,
rti::sub::TopicQuerySelection(dds::topic::Filter("x < 10")));

Now you can use my_reader to take the historical data samples from all matching DataWriters that pass the filter. You can also keep reading “live” data as usual.

With C++17 just approved and C++20 around the corner, we are continuing to update and modernize our C++ API with exciting features. Stay tuned or simply subscribe to the RTI Blog for all of the latest updates!

Getting Started with Connext

Connext® is the world's leading implementation of the Data Distribution Service (DDS) standard for Real-Time Systems. Try a fully-functional version of Connext for 30 days.


Free Trial