RefleX is short for Reflection for DDS-XTypes. The main objective of this library is to create DDS-XTypes compliant types and data directly from native C++ types. RefleX is declarative–i.e., it is not a reflection API. There is no separate code generation step involved (other than compilation). The RefleX library will take your application-level datatypes in C++ and will happily map them to equivalent DDS topic types.
Example
Consider the following simple ShapeType
class.
class ShapeType
{
std::string color_;
int x_, y_, shapesize_;
public:
ShapeType() {}
ShapeType(const std::string & color,
int x, int y, int shapesize)
: color_(color), x_(x), y_(y),
shapesize_(shapesize)
{}
std::string & color() { return color_; }
int & x() { return x_; }
int & y() { return y_; }
int & shapesize() { return shapesize_; }
const std::string & color() const { return color_; }
const int & x() const { return x_; }
const int & y() const { return y_; }
const int & shapesize() const { return shapesize_; }
};
To send and receive instances of this class using DDS, simply add the REFLEX_ADAPT_STRUCT
macro below. Note that color
is the key.
#include "reflex.h"
REFLEX_ADAPT_STRUCT(
ShapeType,
(std::string, color(), REFLEX_KEY)
(int, x())
(int, y())
(int, shapesize()))
The ShapeType
class and its objects can now be used with RTI Connext DDS. Here's the main
program that writes a ShapeType
objects. GenericDataWriter
is an thin shim layer to simplify using DDS DataWriter with RefleX. It is not mandatory, however.
int main (void)
{
// ... setup participant
reflex::pub::GenericDataWriter<ShapeType>
writer(participant, "Square");
ShapeType shape("BLUE", 10, 20, 30);
writer.write(shape);
}
RefleX maps the ShapeType
class to the following ShapeType
IDL, which is inter-operable with the Shapes Demo.
struct ShapeType
{
string<128> color; //@key
long x;
long y;
long shapesize;
};//@Extensibility EXTENSIBLE_EXTENSIBILITY
Why RefleX?
Use Native C++ Types with DDS (IDL-free): IDL representation of DDS types is no longer necessary. Adapted C++ types declarations in the headers are sufficient. With RefleX, you are free to use C++ standard library types, such as STL containers, custom iterators,
shared_ptr
,auto_ptr
,unique_ptr
, etc. The RefleX library has a predefined mapping for each and you can also define your own.Use Declarative Dynamic Data:
DynamicData
andTypeCode
objects can be created declaratively as opposed to procedurally, which quickly gets laborious and repetitive as the complexity of the type increases. RefleX is based on the principle of Don't Repeat Yourself (DRY). RefleX completely eliminates the repetitive work in using theDynamicData
API. Many times, types are known statically but no code generation support is available (e.g., RTI Routing Service adapters). With RefleX, creating aTypeCode
and populating a correspondingDynamicData
object is never more than one line of code!Use Third-party Code Generators: Classes generated by third-party code generation tools can be mapped to DDS topic types. The key is that RefleX works directly off of C++ types. The generated types may use a wide variety of types (e.g., boost containers, custom iterators, etc.). RefleX provides a way to map such types directly to a DDS. For example, with RefleX the types generated by a third-party XSD to C++ compiler can be mapped to DDS by adding an
RTI_ADAPT_STRUCT
macro for each generated type. See an example of mapping OSA-CBM XSD to DDS using the Code Synthesis open-source code generator.Improve Performance: Users of complex XML vocabularies (e.g., XSD) often serialize data to plain-text XML before writing it out to DDS. Such an approach incurs significant performance penalty as data is serialized twice. RefleX does only one serialization as the underlying DynamicData representation is already serialized.
Avoid Glue code: Glue code must often be written because wire-level types may not always match with the application-level types. RefleX allows direct use of application-level types with DDS. Glue code is nearly eliminated. It's all about avoiding repeating yourself.
What powers RefleX?
The Reflex library uses powerful C++ meta-programming (templates and the preprocessor) machinery to iterate over the members of the user-defined type and synthesizes equivalent TypeObject
representation for the type and DynamicData
representation for the state. RTI_ADAPT_STRUCT
macro acts as a substitute for reflection in C++. The macro uses Boost Fusion internally. It is not the kind of reflection in the Java/C# world. It is a macro, which opens the guts of the specified type to the RefleX library (take a look). The key difference is that the process of reflection happens at compile-time. As a consequence, there is no run-time performance penalty for using reflection. The resulting on-the-wire type description is fully compatible with an equivalent type described in IDL. Needless to say, they interoperate.
Architecture
RefleX is based on a simple layered architecture. DDS applications based on the classic C++ DDS API and the new C++ DDS PSM can make use of RefleX.
Native C++ Types Supported by RefleX
- All fundamental types, arrays, multi-dimensional arrays, enumerations
- Struct (with public members) (example)
- Classes (with setter/getter) (example)
- Nested struct/classes (example)
- Standard Template Library (STL)
string
,vector
,list
,set
,map
,array
,tuple
,pair
, iterators, etc. - Raw pointer, smart pointers
- Optional members (e.g., boost::optional)
- User-defined/custom containers (e.g., those that expose STL-compatible iterators, boost.Iterators) (example)
- Class inheritance (example)
- Most combinations of the above
Download and Build
Linux
- Recommended compilers: g++ 4.8, clang 3.3 or better
- export REFLEXHOME, BOOSTHOME (1.46+) and NDDSHOME (5.0.0+)
- export ARCH=i86Linux2.6gcc4.8.2, for example.
- See make/Makefile* for details
- export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$NDDSHOME/lib/$ARCH:$REFLEXHOME/objs/$ARCH
- Build: make -f make/Makefile.i86Linux-gcc CXX=g++48 (g++48 must be in your $PATH)
- Build tests: make/Makefile.i86Linux-gcc test
- Build perf_test: make/Makefile.i86Linux-gcc perf_test
- Build property_test: make/Makefile.i86Linux-gcc prop_test CXX=g++5 CXXSTD=c++14 RANDOM=$RANDOM
Windows
- Use Visual Studio 2013
- Set REFLEXHOME, BOOSTHOME (1.46+), and NDDSHOME (5.1.0+)
- Set PATH=%PATH%;%REFLEXHOME%\objs\i86Win32VS2013;%NDDSHOME%\lib\i86Win32VS2012
- Run %NDDSHOME%\scripts\rtiddsgen -language C++ -namespace -d test idl\complex.idl
- Open win32\reflex-vs2013.sln
Documentation
See RefleX documentation generated using Doxygen.
More reading
License
(c) 2005-2014 Copyright, Real-Time Innovations, Inc. All rights reserved.
RTI grants Licensee a license to use, modify, compile, and create derivative works
of the Software. Licensee has the right to distribute object form only for use with RTI
products. The Software is provided “as is”, with no warranty of any type, including
any warranty for fitness for any purpose. RTI is under no obligation to maintain or
support the Software. RTI shall not be liable for any incidental or consequential
damages arising out of the use or inability to use the software.
Contact
Sumant Tambe (sumant at RTI d0t com)