RTI Routing Service: How to create a transformation plugin
RTI Routing Service provides a transformation SDK in C to support the creation of custom transformation plugins. A route can be created by RTI Routing Service. This route transforms the incoming data, using this custom transformation plugin, and then republishes the updated data.
This article will be based on an example provided by RTI rti_workspace/<version>/examples/routing_service/shapes:
- topic_bridge_w_custom_transf.xml is the XML Configuration for RTI Routing Service.
- transformation/src/shapestransf.c is the transformation plugin code, which will be compiled and loaded dynamically.
- transformation/make: folder with the makefiles.
- transformation/windows: folder with the Visual Studio project.
Steps to create a transformation plugin
- Implement the transformation plugin API and generate a shared library.
- Register that library in the configuration file by creating a <transformation_plugin> tag inside the <transformation_library> tag.
- Instantiate a transformation by creating a <transformation> tag inside the <topic_route> tag.
1. Implement the transformation plugin API
The transformation plugin API is documented here for the current release and here for release 5.3.0. (In 5.3.0 it was only supported in C.)
Through this SDK, you can create a custom transformation plugin. Here is a UML diagram of the plugin model:
Once the transformation plugin is implemented, it is necessary to compile it through makefiles or Visual Studio.
Every transformation plugin will implement the following functions:
Create transformation plugin:
123typedef
struct
RTI_RoutingServiceTransformationPlugin *(*RTI_RoutingServiceTransformationPlugin_create)(
const
struct
RTI_RoutingServiceProperties * properties,
RTI_RoutingServiceEnvironment * env);
Delete the transformation plugin:
123typedef
void
(*RTI_RoutingServiceTransformationPlugin_delete)(
struct
RTI_RoutingServiceTransformationPlugin * plugin,
RTI_RoutingServiceEnvironment * env);
Create a new transformation:
123456typedef
RTI_RoutingServiceTransformation(*RTI_RoutingServiceTransformationPlugin_create_transformation)(
struct
RTI_RoutingServiceTransformationPlugin * plugin,
const
struct
RTI_RoutingServiceTypeInfo * input_type_info,
const
struct
RTI_RoutingServiceTypeInfo * output_type_info,
const
struct
RTI_RoutingServiceProperties * properties,
RTI_RoutingServiceEnvironment * env);
Delete a transformation:
1234typedef
void
(*RTI_RoutingServiceTransformationPlugin_delete_transformation)(
struct
RTI_RoutingServiceTransformationPlugin * transformationPlugin,
RTI_RoutingServiceTransformation transformationObject,
RTI_RoutingServiceEnvironment * env);
- Transform input data into output data:
- outSampleLst: it is possible to modify the Stream sample.
- outInfoLst: It is also possible to modify the DDS_SampleInfo, which is the information that accompanies each sample.
- out_count: number of samples to write by RTI Routing Service.
123456789typedef
void
(*RTI_RoutingServiceTransformation_transform)(
RTI_RoutingServiceTransformation transformation,
RTI_RoutingServiceSample ** out_sample_lst,
RTI_RoutingServiceSampleInfo ** out_info_lst,
unsigned
int
* out_count,
RTI_RoutingServiceSample * in_sample_lst,
RTI_RoutingServiceSampleInfo * in_info_lst,
unsigned
int
in_count,
RTI_RoutingServiceEnvironment * env);
Return loan, indicates that Routing Service is done with the data:
123456typedef
void
(*RTI_RoutingServiceTransformation_return_loan)(
RTI_RoutingServiceTransformation transformation,
RTI_RoutingServiceSample * sample_lst,
RTI_RoutingServiceSampleInfo * info_lst,
unsigned
int
count,
RTI_RoutingServiceEnvironment * env);
Update, called as a result of the remote update command:
1234typedef
void
(*RTI_RoutingServiceTransformation_UpdateFcn)(
RTI_RoutingServiceTransformation transformation,
const
struct
RTI_RoutingServiceProperties * properties,
RTI_RoutingServiceEnvironment * env);
1.1 Implement a transformation between different DataType
In the case of creating a transformation between two different DataTypes is fundamental to take account of:
Define the types in the Transformation Structure:
123456789struct
TestTransformation {
/*
* @brief A reference to the plugin
*/
struct
TestTransformationPlugin * _plugin;
const
struct
DDS_TypeCode * TestA;
const
struct
DDS_TypeCode * TestB;
};
Create the dynamic data output from the type and set the value:
123456789struct
DDS_DynamicData * output = DDS_DynamicData_new(
self->TestB,
&DDS_DynamicDataProperty_t_INITIALIZER);
/* Set the values to the output sample */
retCode = DDS_DynamicData_set_long(
output,
"my_long1"
,
DDS_DYNAMIC_DATA_MEMBER_ID_UNSPECIFIED,
my_long1);
Now it is not possible to create the output from the input sample because they are different dataType.
1 | retCode = DDS_DynamicData_copy(output, input); //Cannot use it for different types |
2. Register Transformation library configuration
The transformation plugin should be provided in the XML configuration file a shared library to RTI Routing Service, which will be loaded dynamically. To register a transformation plugin with RTI Routing Service, you must use the tag <transformation_plugin> within <transformation_library>.
A transformation plugin is defined in the transformation_library tag in the XML Configuration file:
- dll: Path to the shared library containing the implementation of the transformation plugin.
- create_function: Name of the function used to create the transformation plugin, which is implemented in the shared library.
The example provided by RTI in topic_bridge_w_custom_transf.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | < dds > < transformation_library name = "MyTransformationLib" > < transformation_plugin name = "ShapesTransformation" > < dll > $(RTI_EXAMPLES_DIR)/routing_service/shapes/transformation/$(RTI_SHARED_LIB_PREFIX)shapestransf$(RTI_SHARED_LIB_SUFFIX) </ dll > < create_function >ShapesTransformationPlugin_create</ create_function > </ transformation_plugin > </ transformation_library > ... < routing_service > ... </ routing_service > ... </ dds > |
3. Create a transformation through a topic_route
Once a transformation plugin is registered, a route can use it to create a data transformation. In our example provided in the topic_bridge_w_custom_transf.xml, the following route uses a transformation to set a value in the x-coordinate of a ShapeType.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | < topic_route name = "Squares" > < input participant = "1" > < registered_type_name >ShapeType</ registered_type_name > < topic_name >Square</ topic_name > </ input > < output > < topic_name >Square</ topic_name > < registered_type_name >ShapeType</ registered_type_name > </ output > < transformation plugin_name = "MyTransformationLib::ShapesTransformation" > < property > < value > < element > < name >x</ name > < value >50</ value > </ element > </ value > </ property > </ transformation > </ topic_route > |
4. Running the example
We can see how the transformation is done executing the example:
All the steps are here for the current release or here for release 5.3.0.
1 2 3 | $NDDSHOME /bin/rtiroutingservice -cfgFile topic_bridge_w_custom_transf.xml -cfgName example . /objs/x64Linux3gcc5 .4.0 /ShapeType_subscriber . /objs/x64Linux3gcc5 .4.0 /ShapeType_publisher |