C++ mappings: From IDL types to C++ types
Scoped names
The C++ mappings for scoped names use C++
scopes. IDL module are mapped to namespace. For instance, the following
IDL:
module m {
const string str = "scoped string";
};
would map into
namespace m {
const std::string str = "scoped string";
}
Mapping for constants
genom3 IDL constants are mapped to a C++ constant. For
instance, the following IDL:
const long longint = 1; const string str = "string example";
would map into
const int32_t longint = 1; const std::string str = "string example";
Mapping for basic data types
The basic data types have the mappings shown in the table below.
Integer types use the C99 fixed size integer types as provided
by the stdint.h standard header (since the C++ cstdint
header is not part of the C++ at the time of writing this
document).
Users do not have to include this header: the template mapping
generation procedure output the appropriate #include directive
along with the mappings for the integer types.
| IDL | C++ |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type any not implemented yet |
Mapping for enumerated types
The C++ mapping of an IDL enum type is the corresponding
C++ enum. An additional constant is generated to guarantee
that the type occupies a 32 bits wide integer.
For instance, the following IDL:
enum e {
value1,
value2
};
would map, according to the scoped names rules, into
enum e {
value1,
value2,
_unused = 0xffffffff,
};
Mapping for strings
genom3 IDL bounded strings are mapped to nul terminated character
arrays (i.e., C strings). Unbounded strings are mapped to
std::string provided by the C++ standard.
For instance, the following OMG IDL declarations:
typedef string unbounded;
typedef string\<16> bounded;
would map into
typedef std::string unbounded;
typedef char bounded[16];
Mapping for arrays
genom3 IDL arrays map directly to C++ arrays. All array
indices run from 0 to size-1.
For instance, the following IDL:
typedef long array[4][16];
would map into
typedef int32_t array[4][16];
Mapping for structure types
genom3 IDL structures map directly onto C++ `struct`s.
Note that these structures may potentially include padding.
For instance, the following IDL:
struct s {
long a;
long b;
};
would map into
struct s {
int32_t a;
int32_t b;
};
Mapping for union types
genom3 IDL unions map onto C struct`s. The discriminator in the enum is
referred to as `_d, the union itself is referred to as _u.
For instance, the following IDL:
union u switch(long) {
case 1: long a;
case 2: float b;
default: char c;
};
would map into
struct u {
int32_t _d;
union {
int32_t a;
float b;
char c;
} _u;
};
Note that the C++ standard does not allow union members that
have a non-trivial constructor. Consequently, the C++ mapping
for such kind of unions is not allowed in genom3 either. This concerns
sequence`s and `string`s, and structures or unions that
contain such a type. You should thus avoid to define such datatypes in
`genom3 IDL in order to maximize the portability of your definitions.
Mapping for sequence types
genom3 IDL sequences mapping differ for bounded or unbouded
variations of the sequence. The unbounded sequences maps onto the
std::vector template class provided by the C++ standard. The
bounded sequence maps onto a C++ genom::bounded_sequence
template class. The definition of genom::bounded_sequence is very
similar to std::array but provides a variable number of elements.
For instance, the following IDL:
typedef sequence<long> unbounded;
typedef sequence<long,16> bounded;
would map into
typedef std::vector<int32_t> unbounded;
typedef genom::bounded_sequence<int32_t, 16> bounded;
The interface of genom::bounded_sequence is the following:
template <typename T, size_t N>
struct bounded_sequence {
// types:
typedef T value_type;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* iterator;
typedef const value_type* const_iterator;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
value_type e[N];
size_type n;
// No explicit construct/copy/destroy for aggregate type
void fill(const value_type &u);
// iterators:
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
reverse_iterator rbegin();
reverse_iterator rend();
const_reverse_iterator rbegin() const;
const_reverse_iterator rend() const;
const_iterator cbegin() const;
const_iterator cend() const;
const_reverse_iterator crbegin() const;
const_reverse_iterator crend() const;
// capacity:
size_type size() const;
void resize(size_type l, value_type u = value_type());
size_type max_size() const;
bool empty() const;
// element access:
reference operator[](size_type i);
const_reference operator[](size_type i) const;
reference at(size_type i);
const_reference at(size_type i) const;
reference front();
const_reference front() const;
reference back();
const_reference back() const;
value_type *data();
const value_type *data() const;
// modifiers
void swap(bounded_sequence &a);
void clear();
};
Mapping for optional types
genom3 IDL optional types map onto the genom::optional template
class.
For instance, the following IDL:
typedef optional< long > opt;
would map into
typedef genom::optional< int32_t > opt;
The interface of genom::optional is the following:
template <typename T>
struct optional {
// types:
typedef T value_type;
typedef value_type& reference;
typedef const value_type& const_reference;
bool _present;
value_type _value;
};
The _present member, when true, indicates the presence of
valid data in _value. When _present is false, the
_value should be ignored.
Mapping for port types
Simple ports map onto a pure virtual struct providing a
data() and read() or write() methods. The
data() method takes no parameter and returns a constant
reference on the current port data. Input ports may refresh their data
by invoking the read() method, while output ports may publish
new data by invoking the write() method. Both read() and
write() return no value (void).
Ports defined with the multiple flag map onto a similar
pure virtual struct, with the difference that data(),
read() and write() methods take an additional string
(const char *) parameter representing the port element
name. Multiple output ports have two additional open() and
close() members (also accepting a single string parameter) that
dynamically create or destroy ports.
All these method may throw a genom::exception representing an
error code.
For instance, the following IDL:
port in double in_port;
port multiple in double multi_in_port;
port out double out_port;
port multiple out double multi_out_port;
would map into
struct in_port {
virtual const double &data(void) const = 0;
virtual void read(void) = 0;
};
struct multi_in_port {
virtual const double &data(const char *id) const = 0;
virtual void read(const char *id) = 0;
};
struct out_port {
virtual double &data(void) const = 0;
virtual void write(void) = 0;
};
struct multi_out_port {
virtual double &data(const char *id) const = 0;
virtual void write(const char *id) = 0;
virtual void open(const char *id) = 0;
virtual void close(const char *id) = 0;
};
Mapping for remote services
Remote objects map onto a pure virtual struct providing a
call() method. call() takes the same parameters as the
corresponing service definition and return no data (void). It
may throw a genom::exception representing an error code.
For instance, the following IDL:
interface i {
function f(in long i, out double o);
};
component c {
uses i;
};
would map into
namespace c {
struct f {
virtual void call(uint32_t i, double &o) = 0;
};
}
The remote service is invoked in a synchronous manner.
Mapping for native types
genom3 IDL native types map to a C++ struct. The mapping
provides only a forward declaration, and the user has to provide the
actual definition.
For instance, the following IDL:
native opaque;
would map into
struct opaque;
The definition of the structure body is free, and will typically use
native C++ types that cannot be described in IDL. When used as a
parameter of a function, a native type will be passed around as a
pointer on the structure data. Memory management associated with that
pointer must be handled by the user.
Mapping for exceptions
Each defined exception type is defined as a C++ struct that
derives from the generic genom::exception type and implements a
what() method returning a unique identifier for the
exception. Exceptions with members define an additional struct
detail type inside the scope of the exception as well a a
detail member of that type. A global identifier for the
exception is also defined (it is identical to the return value of the
what method).
For example:
exception foo {
long dummy;
};
yields the following C++ declarations:
genom_event foo_id = <unique identifier for exception>;
struct foo : public genom::exception {
struct detail {
uint32_t dummy;
} detail;
const char *what();
} foo_detail;
Exceptions must be thrown with the C++ throw operator.
The identifier for the exception uniquely identifies this exception
type, so that any data of type genom_event can be compared to
an exception id with the == operator.