The Attack of the DDS C++ APIs
Written by Gerardo Pardo-Castellote
December 3, 2014
If you are currently developing Connext DDS applications in C++, you have a single API option: Use a "traditional" DDS API that is derived from the DDS interface definition defined in the OMG IDL language.
Thankfully, things are about to change and you have two more options to choose from:
- A new standard DDS C++ API which defined by the OMG DDS-C++ PSM standard (DDS-PSM-Cxx), and
- the C++ API obtained by applying a new OMG IDL to C++11 standard mapping to the IDL DDS interfaces, see Johnny's post on the subject here.
Curious yet confused? This post will give you some historical context, explain why it makes sense to have both, and where you would use each one.
Context & Rationale
First the basics: The OMG Interface Definition Language (IDL) provides a way to define interfaces and data-types independently of a specific programming language. This means that you can define an interface in IDL just once and then have it automatically mapped to C, C++, Java, C#/.NET, Ada, Python, Ruby, etc. These transformations are defined in the so-called IDL to Language mappings. See the OMG specifications page for a list of the current ones.
Define the interface once, and get it in all the popular languages automatically. It sounds like a great idea, doesn't it? Yes, it is a very nice feature and the reason the OMG DDS Specification defined the DDS functionality at a higher level, using UML, and then the DDS APIs using OMG IDL instead of taking the time to define the API separately for each programming language.
However there is a price to be paid for the convenience of using IDL. Because IDL needs to be mappable to all the programming languages, it provides a "minimal common denominator" and lacks many features that are specific to the different programming languages. When you use a programming language you want to leverage its features and idioms to make the code as clean, readable, and robust as the language allows. If the idioms are absent the code seems clunky.
For example, the IDL lacks generics, so the IDL to C++, Java, and C# does not use templates/generics even in the places that would make the most sense. Also IDL interfaces cannot have overloaded operations, or cannot define operators, the list goes on.
For this reason the DDS SIG decided that the best approach was to create new specifications that define the DDS APIs in the most popular languages, starting with C++ and Java. It is the same DDS specification (same classes, operations, behaviors defined by the UML model in the DDS Specification) but mapped directly each programming language leveraging the features and idioms natural in that language. Apply some elbow grease, meetings, reviews, and votes and you get the DDS C++ API and the DDS Java API specifications.
Choosing Your API & Having the Best Possible Experience
Defining the DDS API directly on a programming language gives the best possible experience to the programmer. As Alex eloquently put it in his recent blog "Create a P2P Distributed Application In Under 35 Lines Of C++11 Code!". So this is typically the best choice.
Why, you may ask, use the DDS API derived from the IDL to C++11 mapping?
It turns out that defining the APIs in IDL is very useful for automated tools and an important capability for component-based programming.
If an application developer uses a component-based programming framework or some other code-generation framework it is isolated from the middleware APIs. The application user programs to the "framework APIs" and the mapping to the "technical middleware layer" is handled by the code generation and the tooling. The IDL provides a nice intermediate representation for the framework which can then generate code that is not tied to a programming language, and the IDL to language mapping handles the rest. In this scenario the IDL to C++11 mapping may be the best approach. The tools can keep using IDL and yet the resulting code is cleaner, more efficient, and robust than the one that would be generated from the "classic" IDL to C++ mapping.
There are other situations where using IDL-derived APIs may be advantageous to the application, for example if they are integrating other technologies and frameworks that also use IDL. In this case the IDL to C++11 mapping may also be the best approach.
What about the old-tried (classic) IDL to C++ API? This also makes sense for people that do not particularly like or cannot use some of the "modern" C++ magic (auto pointers, STL, templated meta programming, etc.). For example some compilers that do not support these advanced features or it these extra libraries would make the code too complex or expensive to certify.
In the end, it is all about choice and ensuring that you have the best tool to do the job. One of the great things about DDS is that allows applications that are written in different programming languages to communicate and share information. Stated another way, DDS gives you a way to have these applications integrated and interoperate. The DDS concepts: DomainParticipant, Topic, DataWriter, DataReader, QoS, Content Filters, are the same across these options, while the specific language APIs can differ. Therefore, using a specific C++ language binding is a matter of choice and convenience, much like deciding to use Java, C, or C#.