1. About Protocol Buffers Extension

RTI® Connext® Protocol Buffers Extension enables the use of Protocol Buffers data types in Connext applications.

Protocol Buffers Extension is an experimental feature in Connext Professional 7.6.0. See Experimental Features in RTI Connext What’s New.

Note

Protocol Buffers Extension is currently supported only on Linux 64-bit Intel architecture.

1.1. Use Cases

Protocol Buffers Definition Language. Protocol Buffers Extension provides support for using the Protocol Buffers message definition language to define the data types used by Connext applications. Developers can specify data types in .proto files, and the toolchain will automatically map them to corresponding DDS-XTYPES types, which serve as the foundation for communication over DDS.

Protocol Buffers to |IDL| Conversion

Generation of Equivalent DDS-XTYPES Types. Protocol Buffers Extension generates .idl files containing DDS-XTYPES types equivalent to the Protocol Buffers types defined in .proto files. This enables easy integration between those Connext applications using the Protocol Buffers data types, and those using the equivalent DDS-XTYPES types, regardless of programming language.

Protocol Buffers C++ Language Binding. Protocol Buffers Extension allows developers to use the C++ message types generated by the Protocol Buffers compiler in combination with Connext’s “Modern” C++ API. Applications can create DataWriter and DataReader endpoints to exchange objects of the Protocol Buffers types directly over DDS topics. Existing components that use these types can be easily and efficiently integrated onto the DDS databus.

Protocol Buffers Integration with DDS

Integration with DDS. The data-types defined using Protocol Buffers are first-class citizens in the Connext platform and can be used just like any other DDS types. Full support is provided for features such as type discovery, type matching, type evolution, dynamic types, dynamic data, content filtering, and more.

The .proto files can be enriched with custom Protocol Buffers options defined to control DDS-specific properties, such as indicating key members. Other options allow developers to take advantage of DDS-XTYPES features not natively available in standard Protocol Buffers. This enhances the integration of Protocol Buffers components with other Connext applications.

1.2. Components

Protocol Buffers Extension consists of two plugins for the Protocol Buffers compiler (protoc), and a set of DDS-specific options for Protocol Buffers types:

1.2.1. IDL4 Converter Plugin

The IDL4 Converter Plugin converts .proto files into equivalent .idl files:

protoc --idl4_out=<outputdir> message.proto
  • Example Input (message.proto):

    syntax = "proto3";
    
    import "other.proto";
    
    package myapp;
    
    message MyMessage {
        int32 foo = 1;
        Other bar = 2;
    }
    
  • Example Output (message.idl):

    #ifndef myapp_message_proto_IDL4_
    #define myapp_message_proto_IDL4_
    
    #include "other.idl"
    
    module myapp {
        @mutable
        struct MyMessage {
            @id(1) int32 foo;
            @id(2) @optional Other bar;
        };
    }; // module myapp
    
    #endif // myapp_message_proto_IDL4_
    

Section Protocol Buffers to DDS-XTYPES Mapping provides a detailed description of the mapping between Protocol Buffers and IDL4 types.

1.2.2. C++ Code-Generator Plugin

The Connext C++ Code-Generator Plugin is used together with Protocol Buffers’s built-in C++ Code Generator to generate C++ classes for each data type, e.g.:

protoc --cpp_out=<outputdir> \
        --connext-cpp_out=<outputdir> \
        message.proto
  • Example Output (message.pb.h, abridged):

    #include "other.pb.h"
    
    // Injected by RTI code generator
    #include "rti/topic/cdr/ProtobufInterpreter.hpp"
    
    namespace myapp {
    
    class MyMessage final : public ::google::protobuf::Message {
    public:
        MyMessage();
        ~MyMessage() override;
    
        bool has_foo() const;
        void clear_foo();
        int32_t foo() const;
    
        bool has_bar() const;
        void clear_bar();
        const ::myapp::Other& bar() const;
        ::myapp::Other* mutable_bar();
        void set_allocated_bar(::myapp::Other* bar);
    
        // Injected by RTI code generator
        template <typename MessageType>
        friend struct ::rti::topic::interpreter::detail::protobuf_message_access;
    
    private:
        int32_t foo_;
        ::myapp::Other* bar_;
    }
    
    } // namespace myapp
    

1.2.3. DDS Options for Protocol Buffers

Additional options are available to control the IDL4 types derived from the Protocol Buffers definitions. See DDS Options for Protocol Buffers. These options are defined using Protocol Buffers syntax and they can be applied after importing the associated .proto file (omg/dds/descriptor.proto).

  • Example Input (message.proto, annotated):

    syntax = "proto3";
    
    import "other.proto";
    
    import "omg/dds/descriptor.proto";
    
    package myapp;
    
    message MyMessage {
        option (.omg.dds.type) = {
            default_id: DDS_DEFAULT_ID,
            auto_id: HASH
        };
    
        int32 foo = 1 [ (.omg.dds.member).key = true ];
        Other bar = 2 [ (.omg.dds.member) = {
          optional: true,
          hash_id: "baz"
        }];
    }
    
  • Example Output (message.idl, customized):

    #ifndef myapp_message_proto_IDL4_
    #define myapp_message_proto_IDL4_
    
    #include "other.idl"
    
    module myapp {
        @mutable
        @autoid(hash)
        struct MyMessage {
            @key int32 foo;
            @hash_id("baz") Other bar;
        };
    }; // module myapp
    
    #endif // myapp_message_proto_IDL4_