IDL - Interface Definition and Language Mapping

This describes defining interfaces using a subset of the Interface Definition Language (IDL).

Authors: Dirk Thomas

Date Written: 2019-03

Last Modified: 2020-07

Scope

This article identifies a subset of the Interface Definition Language (IDL) that can be used to describe interfaces between components. Further it describes how the interfaces are used to generate code in C, C++ and Python.

Supported subset of IDL

ROS 2 supports a subset of the OMG IDL 4.2 specification. Whatever is not listed below is probably not supported at the moment (e.g. enums).

Lexical Conventions

7.2.2 Comments

Both line comments (//) as well as block comments (/* ... */) are being supported.

7.2.3 Identifiers

An identifier must start with an is an ASCII alphabetic characteran followed by any number of ASCII alphabetic, digit and underscore (_) characters.

7.2.6 Literals

All of the following literals are supported:

  • Integer
  • Character
  • String
  • Floating-point
  • Fixed-point

Preprocessing

At the moment there is no preprocessing happening when reading the `.idl files.

Building Blocks

7.4.6.4.1.4 Imports

Imports must be used to reference other .idl file which declare data types used in this .idl file.

7.4.1.4.2 Modules

Each module must contain at least one definition and they can be nested. For ROS interfaces the first module level commonly represents the package name, the second module level distinguishes the type of the interface (msg, srv, action).

7.4.1.4.3 Constants

7.4.1.4.4.4.1 Structures

A structure must contain at least one member.

Basic Types

7.4.1.4.4.2.1 Integer Types

IDL type Value range
short -2^15 … 2^15 - 1
unsigned short 0 … 2^16 - 1
long -2^31 … 2^31 - 1
unsigned long 0 … 2^32 - 1
long long -2^63 … 2^63 - 1
unsigned long long 0 … 2^64 - 1

7.4.1.4.4.2.2 Floating-Point Types

IDL type Format
float IEEE single-precision floating point number
double IEEE double-precision floating point number
long double IEEE double-extended floating-point number

7.4.1.4.4.2.3 Char Type

IDL type Value range
char A 8-bit single-byte character with a numerical value between 0 and 255 (see 7.2.6.2.1)

The type can store a single-byte character from any byte-oriented code set, or when used in an array, encode a multi-byte character from a multi-byte code set.

7.4.1.4.4.2.4 Wide Char Type

IDL type Value range
wchar A 16-bit wide character

While the IDL spec only defines the size of wchar as implementation-dependent the DDS-XTypes specification 1.2 defines it with 16-bit.

7.4.1.4.4.2.5 Boolean Type

IDL type Value range
boolean One of the values TRUE and FALSE

7.4.1.4.4.2.6 Octet Types

IDL type Value range
octet opaque 8-bit

7.4.13.4.4 8-bits Integers

IDL type Value range
int8 -2^7 … 2^7 - 1
uint8 0 … 2^8 - 1

7.4.13.4.5 Explicitly-named Integer Types

IDL type Equivalent IDL type
int16 short
uint16 unsigned short
int32 long
uint32 unsigned long
int64 long long
uint64 unsigned long long

Template Types

7.4.1.4.4.3.1 Sequences

IDL type Value range
sequence<type_spec> sequence of items of the specific type_spec
  the sequence is unbounded and no maximum size is specified
sequence<type_spec, N> sequence of of up to N items of the specified type_spec
  the sequence is bounded and contain between 0 and N items

7.4.1.4.4.3.2 Strings

IDL type Value range
string sequence of char except null

7.4.1.4.4.3.3 Wstrings

IDL type Value range
wstring sequence of wchar except null

Constructed Types

7.4.1.4.4.4.1 Structures

A structure is a grouping of at least one member.

7.4.1.4.4.4.3 Enumerations

An enumerated type consist of an ordered list of enumerators.

7.4.1.4.4.5 Arrays

A multidimensional, fixed-size array is defined by the type of each item and the explicit sizes for each dimension. For now only a one-dimensional, fixed-size array is supported though.

Annotations

The syntax for arbitrary annotations is supported. How each annotation type is being handled depends on the code generation described below.

Code Generation

TODO: All of this too

Constraint Checking

Generated code for messages is only guaranteed to enforce constraints when a message is published. For example, there might not be an error when a field constrained to be a fixed size array is assigned an array with the wrong size. This could be inconsistent across client library implementations depending on language features and performance cost. In the future any client library may add additional constraint checking when a field is set or modified. Users of generated message code should assume constraints could be enforced at any time to be compatible with such a change.

Type Mapping

The next table defines how IDL types are mapped to the following programming languages:

  • C11 (or higher)
  • C++11 (or higher)
  • Python 3 (or higher)
IDL type C type C++ type Python type
float float float float
double double double float
long double long double long double2 float
char unsigned char unsigned char str with length 1
wchar char16_t char16_t str with length 1
boolean _Bool bool bool
octet unsigned char std::byte1 bytes with length 1
int8 int8_t int8_t int
uint8 uint8_t uint8_t int
int16 int16_t int16_t int
uint16 uint16_t uint16_t int
int32 int32_t int32_t int
uint32 uint32_t uint32_t int
int64 int64_t int64_t int
uint64 uint64_t uint64_t int
  1. If std::byte is not available then unsigned char is used instead.
  2. Users should research the support for long double with their choice of middleware and platform. For example, it is only 64 bits when using Visual Studio.

The next table defines how IDL templated and constructed types are mapped to the programming languages (unless specified otherwise below). When specified T is either one of the types above or an IDL struct. N is the upper limit of a bounded type.

IDL type C type C++ type Python type
T[N] T[N] std::array<T, N> list
sequence<T> struct {size_t, T * } std::vector<T> list
sequence<T, N> struct {size_t, T * }, size_t N std::vector<T> list
string char * std::string str
string<N> char * std::string str
wstring char16_t * std::u16string str
wstring<N> char16_t * std::u16string str

These array and sequence types have special mappings. If a cell is blank then the default mapping is used.

IDL type   C type C++ type Python type  
T[N] for numeric types T:
float, double,
int8, uint8,
int16, uint16,
int32, uint32,
int64, uint64
- - numpy.ndarray(
  shape=(N, ),
  dtype=numpy.DT)
where DT is determined by T:
float -> float32,
double -> float64,
intX -> intX,
uintX -> uintX
sequence<T>
sequence<T, N>
for numeric types T:
float, double,
int8, uint8,
int16, uint16,
int32, uint32,
int64, uint64
- - array.array(typecode=TC) where TC is determined by T:
float -> f,
double -> d,
int8 -> b, uint8 -> B,
int16 -> h, uint16 -> H,
int32 -> l, uint32 -> L,
int64 -> q, uint64 -> Q
octet[N]   - - bytes  
sequence<octet>   - - bytes  
sequence<octet, N>   - - bytes  

Standardized Annotations

8.3.2.1 @key Annotation

ROS 2 nodes exchange information of a certain real world object by means of topics. Every message in a topic is known as data sample and represents an update to the status of the object.

Topic instances are a way of multiplexing the transmission of updates of several objects of the same logical kind over the same resource, i.e. the topic. In a keyed topic, every message is associated with a topic instance and each topic instance is identified by a unique key. In this sense, keys can be thought as the primary key of a database. This key allows nodes to update different states of the same kind. In consequence, all data samples sharing the same key value refer to the same object.

The @key annotation allows indicating that a data member is part of the key, which can have zero or more key fields and can be applied to structure fields of various types. The following example shows how to define a keyed message using the IDL format:

# KeyedMsgName.idl
module package_name {
  module msg {
    struct KeyedMsgName {
      @key long member1;
      string member2;
    };
  };
};

Currently, the message interface format that supports the @key annotation is .idl. Hence, .msg and .srv do not support the @key annotation yet. Please refer to Conversion to IDL for further information on the equivalence and conversion among them.

The general-purpose idl types including primitive types, sequences, strings and structs can be annotated as keys. Following are some examples:

Type Key Members
struct NoKey
{ boolean member1;
long member2;
long member3; }
None
struct SimpleKey
{ @key long member1;
long member2; }
member1
struct ArrayKey
{ @key long member1[3]; }
member1[0]
member1[1]
member1[2]
struct StringKey
{ @key string member1;
long member2}
member1
struct NestedNoKey
{ SimpleKey member1;
long member2; }
None
struct NestedKey
{ @key SimpleKey member1;
long member2; }
member1.member1
struct NestedKey2
{ @key NoKey member1;
long member2; }
member1.member1
member1.member2
member1.member3
struct ComplexNestedKey
{ @key NestedNoKey member1;
long member2; }
member1.member1.member1
member1.member2

8.3.3.1 @default Annotation

The default value is being used to initialize struct members.

8.3.5.1 @verbatim Annotation

When the value comment is passed as the language parameter the text parameter is used as the docblock for the annotated element across all supported programming languages.