Using DynamicType and DynamicData.
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;
};
An example topic-type.
Definition: types.dxx:34
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)
{
StructType foo(
"Foo", {
Member("x", primitive_type<int32_t>()).key(true),
Member("y", primitive_type<int32_t>())
}
);
StructType mytype("MyType");
mytype.add_member(Member("my_long", primitive_type<int32_t>()));
mytype.add_member(Member("my_string", StringType(512)));
mytype.add_member(Member("my_foo", foo));
mytype.add_member(Member("my_sequence", SequenceType(primitive_type<int32_t>(), 10)));
mytype.add_member(Member("my_array", ArrayType(foo, 5)));
mytype.add_member(Member(
"my_optional", foo).
optional(
true));
return mytype;
}
<<value-type>> Represents and IDL struct type
Definition: StructTypeImpl.hpp:34
dds::core::optional< T > optional
Optional type according to the IDL4-C++ OMG specification. Alias of dds::core::optional.
Definition: optional.hpp:37
Contains the types and functions to support Extensible Types.
Definition: dds/core/corefwd.hpp:54
void print_idl(const DynamicType &type, unsigned int indent=0)
<<extension>> Prints the IDL representation of this DynamicType to the standard output
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="https://community.rti.com/schema/current/rti_dds_profiles.xsd">
<types>
<struct name= "Foo">
<member name="x" type="int32" key="true"/>
<member name="y" type="int32"/>
</struct>
<struct name= "MyType">
<member name="my_long" type="int32"/>
<member name="my_string" stringMaxLength="512" type="string"/>
<member name="my_foo" type="nonBasic" nonBasicTypeName= "Foo"/>
<member name="my_sequence" sequenceMaxLength="10" type="int32"/>
<member name="my_array" type="nonBasic" nonBasicTypeName= "Foo" arrayDimensions="5"/>
<member name="my_optional" type="nonBasic" nonBasicTypeName= "Foo" optional="true"/>
</struct>
</types>
</dds>
And then load it as follows:
const DynamicType& mytype = qos_provider.extensions().type("MyType");
const StructType& mytype_struct = static_cast<const StructType&>(mytype);
<<reference-type>> The QosProvider class provides a way for a user to control and access the XML QoS ...
Definition: TQosProvider.hpp:162
- 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:
Provides a DynamicType that represents an IDL-generated type.
Definition: rti/topic/TopicTraits.hpp:165
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:
basic_string< char, rti::core::memory::OsapiAllocator< char > > string
A string convertible to std::string and with similar functionality.
Definition: String.hpp:266
dds::core::xtypes::StructType create_type_from_tuple(const std::string &name)
<<C++11>> <<experimental>> <<extension>> Creates a StructType from a list of types or a std::tuple
Definition: DynamicDataTuples.hpp:232
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.
StructType mytype = create_mytype();
DynamicData sample(mytype);
sample.value("my_long", 23);
DynamicData foo_data(mytype.
member(
"my_foo").type());
foo_data.value("x", 1);
foo_data.value("y", 2);
sample.value("my_foo", foo_data);
loaned_member.
get().value(
"x", 2);
loaned_member.
get().value(
"y", 3);
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);
sample.value("my_optional", foo_data);
sample.clear_optional_member("my_optional");
writer.write(sample);
std::cout << sample << std::endl;
const MemberType & member(MemberIndex index) const
Gets a member by its index.
<<reference-type>> Container for all dds::core::Entity objects.
Definition: TDomainParticipant.hpp:63
<<reference-type>> Allows an application to publish data for a dds::topic::Topic
Definition: TDataWriter.hpp:58
<<reference-type>> A publisher is the object responsible for the actual dissemination of publications...
Definition: TPublisher.hpp:52
<<reference-type>> Topic is the most basic description of the data to be published and subscribed.
Definition: TTopic.hpp:56
<<move-only-type>> Gives temporary access to a member of another DynamicData object.
Definition: DynamicDataImpl.hpp:962
void return_loan()
Explicitly returns the loan.
DynamicData & get()
Obtains the loaned DynamicData object representing a member of DynamicData object.
Definition: DynamicDataImpl.hpp:989
Subscribing to data using DynamicData
using namespace std;
StructType mytype = create_mytype();
for (auto sample : samples) {
if (sample.info().valid()) {
DynamicData& data = const_cast<DynamicData&>(sample.data());
cout << data.value<int32_t>("my_long") << endl;
DynamicData foo_copy = data.value<DynamicData>("my_foo");
cout << foo_copy.value<int32_t>("x") << endl;
LoanedDynamicData loaned_member = data.loan_value("my_foo");
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");
data.get_values("my_sequence", sequence_values);
loaned_member = data.loan_value("my_array");
for (size_t i = 1; i <= loaned_member.get().member_count(); i++) {
LoanedDynamicData array_element = loaned_member.
get().loan_value(i);
cout << array_element.get().value<int32_t>("x") << endl;
cout << array_element.get().value<int32_t>("y") << endl;
}
if (data.member_exists("my_optional")) {
foo_copy = data.value<DynamicData>("my_optional");
cout << foo_copy.value<int32_t>("x") << endl;
cout << foo_copy.value<int32_t>("y") << endl;
} else {
cout << "my_optional is not set" << endl;
}
}
}
<<reference-type>> Allows the application to: (1) declare the data it wishes to receive (i....
Definition: TDataReader.hpp:74
<<move-only-type>> Provides temporary access to a collection of samples (data and info) from a DataRe...
Definition: LoanedSamplesImpl.hpp:77
<<reference-type>> A subscriber is the object responsible for actually receiving data from a subscrip...
Definition: TSubscriber.hpp:49
<<extension>> Extensions to dds::core::xtypes
Definition: rti/core/corefwd.hpp:69
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:
DynamicData sample(mytype);
sample, std::make_tuple(10, 50.5,
std::string(
"Hello")));
writer.write(sample);
std::cout << sample << std::endl;
void set_tuple(dds::core::xtypes::DynamicData &data, const std::tuple< Types... > &value)
<<C++11>> <<experimental>> <<extension>> Assigns the values of a std::tuple to a DynamicData object a...
Definition: DynamicDataTuples.hpp:149
And this is a subscriber:
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;
}
}
std::tuple< Types... > get_tuple(const dds::core::xtypes::DynamicData &data)
<<C++11>> <<experimental>> <<extension>> Retrieves all the values of a DynamicData object into an std...
Definition: DynamicDataTuples.hpp:96