Using DynamicType and DynamicData.
More...
Using DynamicType and DynamicData.
The following #includes are needed for the examples on this page
#include <dds/core/ddscore.hpp>
#include <dds/pub/ddspub.hpp>
#include <dds/sub/ddssub.hpp>
#include "Foo.hpp"
Creating a DynamicType
In this section we'll see the different ways to create a dds::core::xtypes::DynamicType that represents the following IDL type MyType:
long x;
long y;
};
struct MyType {
long my_long;
string<512> my_string;
sequence<long, 10> my_sequence;
};
Create a DynamicType by instantiating it and adding members
(Note this example uses C++11 code that can easily be converted to similar C++03 code)
{
using namespace dds::core::xtypes;
"Foo", {
Member(
"x", primitive_type<int32_t>()).
key(
true),
Member(
"y", primitive_type<int32_t>())
}
);
mytype.add_member(
Member(
"my_long", primitive_type<int32_t>()));
mytype.add_member(
Member(
"my_foo", foo));
mytype.add_member(
Member(
"my_optional", foo).optional(
true));
return mytype;
}
Create a DynamicType from an XML description
We can define the type in this XML file, MyType.xml:
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="rti_dds_qos_profiles.xsd">
<type_library name="MyTypes">
<struct name= "Foo">
<member name=
"x" type=
"long" key=
"true"/>
<member name=
"y" type=
"long"/>
</struct>
<struct name= "MyType">
<member name=
"my_long" type=
"long"/>
<member name=
"my_string" stringMaxLength=
"512" type=
"string"/>
<member name=
"my_foo" type=
"nonBasic" nonBasicTypeName=
"Foo"/>
<member name=
"my_sequence" sequenceMaxLength=
"10" id=
"3" type=
"long"/>
<member name=
"my_array" type=
"nonBasic" nonBasicTypeName=
"Foo" arrayDimensions=
"5"/>
<member name=
"my_optional" type=
"nonBasic" nonBasicTypeName=
"Foo" optional=
"true"/>
</struct>
</type_library>
</dds>
And then load it as follows:
using namespace dds::core::xtypes;
const DynamicType& mytype = qos_provider->type(
"MyTypes",
"MyType");
- See Also
- Qos Provider Use Cases
Get the DynamicType from its equivalent IDL-generated type
<<extension>> When we have the IDL type definition at hand, obtaining its equivalent DynamicType is as simple as:
Create a DynamicType using tuples
<<C++11>> <<experimental>> <<extension>> Note this code requires the additional header <rti/core/xtypes/DynamicDataTuples.hpp>
.
Since this feature only supports structures containing primitive types or strings, we'll create the following simpler IDL type:
struct MyOtherType {
long m1;
double m2;
string m3;
};
We can create the type in a single line:
For convenience, we can also use a std::tuple
, which allows us to typedef it:
typedef std::tuple<int32_t, double, std::string> MyOtherTypeTuple;
mytype = rti::core::xtypes::create_type_from_tuple<MyOtherTypeTuple>("MyOtherType");
Using DynamicData
Now that we know how to create a DynamicType, we will see how to use DynamicData to publish and subscribe to data that we can manipulate reflectively.
We will use the DynamicType that we created before.
Publishing data using DynamicData
Make sure you are already familiar with the regular publication example.
Unlike the regular publication example, using dynamic data we can write code where the type is unknown at compilation type.
using namespace dds::core::xtypes;
sample.value("my_long", 23);
foo_data.value("y", 2);
sample.value("my_foo", foo_data);
loaned_member.get().value("y", 3);
loaned_member.return_loan();
std::vector<int32_t> sequence_values;
sequence_values.push_back(10);
sequence_values.push_back(20);
sequence_values.push_back(30);
sample.set_values("my_sequence", sequence_values);
loaned_member = sample.loan_value("my_array");
array_element.get().value("x", 10);
array_element.get().value("y", 11);
loaned_member.get().loan_value(array_element, 2);
array_element.get().value("x", 20);
array_element.get().value("y", 21);
array_element.return_loan();
loaned_member.return_loan();
sample.value("my_optional", foo_data);
sample.clear_optional_member("my_optional");
writer.write(sample);
std::cout << sample << std::endl;
Subscribing to data using DynamicData
using namespace dds::core::xtypes;
using namespace rti::core::xtypes;
using namespace std;
for (auto sample : samples) {
if (sample.info().valid()) {
cout << data.
value<int32_t>(
"my_long") << endl;
cout << foo_copy.
value<int32_t>(
"x") << endl;
cout << loaned_member.get().value<int32_t>("y") << endl;
loaned_member.return_loan();
cout << data.
loan_value(
"my_foo").get().value<int32_t>(
"y") << endl;
std::vector<int32_t> sequence_values = data.
get_values<int32_t>(
"my_sequence");
for (size_t i = 1; i <= loaned_member.get().member_count(); i++) {
cout << array_element.
get().
value<int32_t>(
"x") << endl;
cout << array_element.
get().
value<int32_t>(
"y") << endl;
}
cout << foo_copy.
value<int32_t>(
"x") << endl;
cout << foo_copy.value<int32_t>("y") << endl;
} else {
cout << "my_optional is not set" << endl;
}
}
}
Manipulating data reflectively using C++ tuples
<<C++11>> <<experimental>> <<extension>>
This feature allows publishing and subscribing to simple data types without code generation and directly using C++ types instead of the DynamicData getters and setters.
This is an example publisher:
using namespace dds::core::xtypes;
sample, std::make_tuple(10, 50.5,
std::string(
"Hello")));
writer.write(sample);
std::cout << sample << std::endl;
And this is a subscriber:
using namespace dds::core::xtypes;
using namespace rti::core::xtypes;
for (auto sample : samples) {
if (sample.info().valid()) {
std::cout << std::get<0>(my_tuple) << std::endl;
std::cout << std::get<1>(my_tuple) << std::endl;
std::cout << std::get<2>(my_tuple) << std::endl;
}
}