目录
1、需求背景
在使用OpenDDS中,需要对不同场景设计出不同的qos方案配置。但是每次写在代码中,后续维护扩展均受限,为此需要使用xml文件配置的方法。其实OpenDDS源码中已经提供了xml配置的方法,但是由于没有编译xml解析库,所以这部分的库就没有生成出来。
2、基础环境
- VS2019
- perl Opendds ace+tao 均已完成编译。
- cmake(3.27)
3、编译xercesc
3.1、下载xercesc
官网链接:http://xerces.apache.org/xerces-c/download.cgi
在Source Distributions 区域找最新的zip下载即可。
3.2、编译xercesc
解压下载好的库后,基本目录结构如下图所示:
我们打开cmake-gui软件。需要填写souce code 和 build binaries 俩个路径。分别为源码路径和编译路径。然后点击【Configure】按钮,在弹出的界面选择VS2019其他默认即可。
然后在下面的CMAKE_INSTALL_PREFIX属性设置安装路径。这里我的DDS路径为D:OpenDDS,所以我安装在了OpenDDS路径下。
再次点击Configure 完成后,点击 Generate按钮。
生成后,点击Open Project按钮,打开工程。
选择Debug-64环境后,打开CMakePredefinedTargets文件夹中找到ALL_BUILD,右击编译。完成后,找到下面的INSTALL工程,右击编译。就会把所编译生成的文件以及头文件输出到你在cmake那块配置的路径中。至此,xercesc的编译就完成了。
4、编译ACE_XML_Utils
ACE_XML_Utils需要xerces库的支持,所以在编译ACE和TAO时并没有生成。
4.1、生成XML_Utils解决方案
注:需要使用VS2019的命令行
在 %OpenDDS%\ACE_wrappers\ace\XML_Utils\路径下执行命令:
perl mwc.pl -type vs2019
在该路径下就会生成ACE_XML_Utils.sln
4.2、编译XML_Utils
点击XML_Utils.sln打开工程。
在属性中需要增加以下配置:
在C/C++常规中增加xerces-c的头文件路径(D:\OpenDDS\xerces-c\include)
在链接器常规中增加xerces-c的库文件路径(D:\OpenDDS\xerces-c\lib)
在链接器输入中增加xerces-c_3D.lib库文件。(Debug是xerces-c_3D.lib,Release是xerces-c_3.lib)
最后编译XML_Utils工程。成功生成。
5、编译QOS_XML_XSC_Handlerd
5.1、生成QOS_XML_XSC_Handlerd解决方案
注:需要使用VS2019的命令行
在 %OpenDDS%\dds\DCPS\QOS_XML_Handler\路径下执行命令:
perl mwc.pl -type vs2019
在该路径下就会生成ACE_XML_Utils.sln
5.2、编译QOS_XML_XSC_Handlerd
点击QOS_XML_XSC_Handlerd.sln打开工程。
在属性中需要增加以下配置:
在C/C++常规中增加xerces-c的头文件路径(D:\OpenDDS\xerces-c\include)
在链接器常规中增加xerces-c的库文件路径(D:\OpenDDS\xerces-c\lib)
在链接器输入中增加xerces-c_3D.lib库文件。(Debug是xerces-c_3D.lib,Release是xerces-c_3.lib)
编译工程,成功生成。
6、测试例子
在%OpenDDS%\tests\DCPS\QoS_XML\dump有xml配置读取的例子。
6.1、生成dump解决方案
注:需要使用VS2019的命令行
在 %OpenDDS%\dds\DCPS\QOS_XML_Handler\路径下执行命令:
perl mwc.pl -type vs2019 -features xerces=1
在该路径下就会生成dump.sln文件
6.2、编译dump
点击dump.sln打开工程。在qos_dump.cpp中就有所有的qos读取示例。
代码如下:
cpp
#include "dds/DCPS/QOS_XML_Handler/QOS_XML_Loader.h"
#include "dds/DdsDcpsC.h"
int ACE_TMAIN (int, ACE_TCHAR *[])
{
int retval = 0;
try
{
OpenDDS::DCPS::QOS_XML_Loader xml_loader;
DDS::ReturnCode_t const retcode = xml_loader.init (ACE_TEXT ("qos#TestProfile"));
if (retcode == DDS::RETCODE_OK)
{
DDS::ReturnCode_t retcode_qos;
::DDS::DataWriterQos dw_qos;
retcode_qos = xml_loader.get_datawriter_qos (
dw_qos,
ACE_TEXT("qos#TestProfile"),
ACE_TEXT("TopicName"));
if (retcode_qos != DDS::RETCODE_OK)
{
ACE_ERROR ((LM_ERROR, "MAIN - "
"get_datawriter_qos return an error. Retcode <%d>\n",
retcode_qos));
++retval;
}
if (dw_qos.history.kind != ::DDS::KEEP_ALL_HISTORY_QOS)
{
ACE_ERROR ((LM_ERROR, "MAIN - "
"get_datawriter_qos return an invalid history kind.\n"));
++retval;
}
if (dw_qos.history.depth != 5)
{
ACE_ERROR ((LM_ERROR, "MAIN - "
"get_datawriter_qos return an invalid history depth.\n"));
++retval;
}
::DDS::DataReaderQos dr_qos;
retcode_qos = xml_loader.get_datareader_qos (
dr_qos,
ACE_TEXT("qos#TestProfile"),
ACE_TEXT("TopicName"));
if (retcode_qos != DDS::RETCODE_OK)
{
ACE_ERROR ((LM_ERROR, "MAIN - "
"get_datareader_qos return an error. Retcode <%d>\n",
retcode_qos));
++retval;
}
if (dr_qos.type_consistency.ignore_sequence_bounds != true)
{
ACE_ERROR ((LM_ERROR, "PARSEXML - "
"get_datareader_qos returned an invalid type type_consistency ignore_sequence_bounds.\n"));
++retval;
}
if (dr_qos.type_consistency.ignore_string_bounds != true)
{
ACE_ERROR ((LM_ERROR, "PARSEXML - "
"get_datareader_qos return an invalid type type_consistency ignore_string_bounds.\n"));
++retval;
}
if (dr_qos.type_consistency.ignore_member_names != true)
{
ACE_ERROR ((LM_ERROR, "PARSEXML - "
"get_datareader_qos return an invalid type type_consistency ignore_member_names.\n"));
++retval;
}
if (dr_qos.type_consistency.prevent_type_widening != true)
{
ACE_ERROR ((LM_ERROR, "PARSEXML - "
"get_datareader_qos return an invalid type type_consistency prevent_type_widening.\n"));
++retval;
}
if (dr_qos.type_consistency.force_type_validation != true)
{
ACE_ERROR ((LM_ERROR, "PARSEXML - "
"get_datareader_qos return an invalid type type_consistency force_type_validation.\n"));
++retval;
}
if (dr_qos.representation.value.length() != 2)
{
ACE_ERROR ((LM_ERROR, "PARSEXML - "
"get_datareader_qos return an invalid length %d for data_representation.\n",
dr_qos.representation.value.length()));
++retval;
}
::DDS::TopicQos tp_qos;
retcode_qos = xml_loader.get_topic_qos (
tp_qos,
ACE_TEXT("qos#TestProfile"),
ACE_TEXT("TopicName"));
if (retcode_qos != DDS::RETCODE_OK)
{
ACE_ERROR ((LM_ERROR, "MAIN - "
"get_topic_qos return an error. Retcode <%d>\n",
retcode_qos));
++retval;
}
if (tp_qos.durability_service.history_kind != DDS::KEEP_LAST_HISTORY_QOS)
{
ACE_ERROR ((LM_ERROR, "PARSEXML - "
"get_topic_qos returned an invalid type durability_service history_kind.\n"));
++retval;
}
::DDS::PublisherQos pub_qos;
retcode_qos = xml_loader.get_publisher_qos (
pub_qos,
ACE_TEXT("qos#TestProfile"));
if (retcode_qos != DDS::RETCODE_OK)
{
ACE_ERROR ((LM_ERROR, "MAIN - "
"get_publisher_qos return an error. Retcode <%d>\n",
retcode_qos));
++retval;
}
::DDS::SubscriberQos sub_qos;
retcode_qos = xml_loader.get_subscriber_qos (
sub_qos,
ACE_TEXT("qos#TestProfile"));
if (retcode_qos != DDS::RETCODE_OK)
{
ACE_ERROR ((LM_ERROR, "MAIN - "
"get_subscriber_qos return an error. Retcode <%d>\n",
retcode_qos));
++retval;
}
::DDS::DomainParticipantQos dp_qos;
retcode_qos = xml_loader.get_participant_qos (
dp_qos,
ACE_TEXT("qos#TestProfile"));
if (retcode_qos != DDS::RETCODE_OK)
{
ACE_ERROR ((LM_ERROR, "MAIN - "
"get_participant_qos return an error. Retcode <%d>\n",
retcode_qos));
++retval;
}
}
else
{
ACE_ERROR ((LM_ERROR, "MAIN - Init return an error. Retcode <%d>\n",
retcode));
++retval;
}
}
catch (const CORBA::Exception& ex)
{
ex._tao_print_exception ("QOS_Dump::main\n");
return -1;
}
catch (...)
{
ACE_ERROR ((LM_ERROR, ACE_TEXT ("Unexpected exception\n")));
return 1;
}
return retval;
}
6.3、OpenDDS的xml格式
xml
<?xml version="1.0" encoding="UTF-8"?>
<dds xmlns="http://www.omg.org/dds"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.omg.org/dds dds_qos.xsd">
<qos_profile name="TestProfile">
<datareader_qos>
<representation>
<value>
<element>XCDR_DATA_REPRESENTATION</element>
<element>XCDR2_DATA_REPRESENTATION</element>
</value>
</representation>
<type_consistency>
<kind>ALLOW_TYPE_COERCION</kind>
<ignore_sequence_bounds>true</ignore_sequence_bounds>
<ignore_string_bounds>true</ignore_string_bounds>
<ignore_member_names>true</ignore_member_names>
<prevent_type_widening>true</prevent_type_widening>
<force_type_validation>true</force_type_validation>
</type_consistency>
<durability>
<kind>VOLATILE_DURABILITY_QOS</kind>
</durability>
<deadline>
<period>
<sec>DURATION_INFINITE_SEC</sec>
<nanosec>DURATION_INFINITE_NSEC</nanosec>
</period>
</deadline>
<latency_budget>
<duration>
<sec>0</sec>
<nanosec>0</nanosec>
</duration>
</latency_budget>
<liveliness>
<kind>AUTOMATIC_LIVELINESS_QOS</kind>
<lease_duration>
<sec>DURATION_INFINITE_SEC</sec>
<nanosec>DURATION_INFINITE_NSEC</nanosec>
</lease_duration>
</liveliness>
<reliability>
<kind>BEST_EFFORT_RELIABILITY_QOS</kind>
<max_blocking_time>
<sec>0</sec>
<nanosec>100000000</nanosec>
</max_blocking_time>
</reliability>
<destination_order>
<kind>BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS</kind>
</destination_order>
<history>
<kind>KEEP_LAST_HISTORY_QOS</kind>
<depth>1</depth>
</history>
<resource_limits>
<max_samples>LENGTH_UNLIMITED</max_samples>
<max_instances>LENGTH_UNLIMITED</max_instances>
<max_samples_per_instance>LENGTH_UNLIMITED</max_samples_per_instance>
</resource_limits>
<!--user_data>
<value></value>
</user_data-->
<ownership>
<kind>SHARED_OWNERSHIP_QOS</kind>
</ownership>
<time_based_filter>
<minimum_separation>
<sec>0</sec>
<nanosec>0</nanosec>
</minimum_separation>
</time_based_filter>
<reader_data_lifecycle>
<autopurge_nowriter_samples_delay>
<sec>DURATION_INFINITE_SEC</sec>
<nanosec>DURATION_INFINITE_NSEC</nanosec>
</autopurge_nowriter_samples_delay>
<autopurge_disposed_samples_delay>
<sec>DURATION_INFINITE_SEC</sec>
<nanosec>DURATION_INFINITE_NSEC</nanosec>
</autopurge_disposed_samples_delay>
</reader_data_lifecycle>
</datareader_qos>
<datawriter_qos>
<durability>
<kind>VOLATILE_DURABILITY_QOS</kind>
</durability>
<durability_service>
<service_cleanup_delay>
<sec>0</sec>
<nanosec>0</nanosec>
</service_cleanup_delay>
<history_kind>KEEP_LAST_HISTORY_QOS</history_kind>
<history_depth>1</history_depth>
<max_samples>LENGTH_UNLIMITED</max_samples>
<max_instances>LENGTH_UNLIMITED</max_instances>
<max_samples_per_instance>LENGTH_UNLIMITED</max_samples_per_instance>
</durability_service>
<deadline>
<period>
<sec>DURATION_INFINITE_SEC</sec>
<nanosec>DURATION_INFINITE_NSEC</nanosec>
</period>
</deadline>
<latency_budget>
<duration>
<sec>0</sec>
<nanosec>0</nanosec>
</duration>
</latency_budget>
<liveliness>
<kind>AUTOMATIC_LIVELINESS_QOS</kind>
<lease_duration>
<sec>DURATION_INFINITE_SEC</sec>
<nanosec>DURATION_INFINITE_NSEC</nanosec>
</lease_duration>
</liveliness>
<reliability>
<kind>RELIABLE_RELIABILITY_QOS</kind>
<max_blocking_time>
<sec>0</sec>
<nanosec>100000000</nanosec>
</max_blocking_time>
</reliability>
<destination_order>
<kind>BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS</kind>
</destination_order>
<history>
<kind>KEEP_ALL_HISTORY_QOS</kind>
<depth>5</depth>
</history>
<resource_limits>
<max_samples>LENGTH_UNLIMITED</max_samples>
<max_instances>LENGTH_UNLIMITED</max_instances>
<max_samples_per_instance>LENGTH_UNLIMITED</max_samples_per_instance>
</resource_limits>
<transport_priority>
<value>0</value>
</transport_priority>
<lifespan>
<duration>
<sec>DURATION_INFINITE_SEC</sec>
<nanosec>DURATION_INFINITE_NSEC</nanosec>
</duration>
</lifespan>
<!--user_data>
<value></value>
</user_data-->
<ownership>
<kind>SHARED_OWNERSHIP_QOS</kind>
</ownership>
<ownership_strength>
<value>0</value>
</ownership_strength>
<writer_data_lifecycle>
<autodispose_unregistered_instances>true</autodispose_unregistered_instances>
</writer_data_lifecycle>
</datawriter_qos>
<domainparticipant_qos>
<!--user_data>
<value></value>
</user_data-->
<entity_factory>
<autoenable_created_entities>true</autoenable_created_entities>
</entity_factory>
</domainparticipant_qos>
<subscriber_qos>
<presentation>
<access_scope>INSTANCE_PRESENTATION_QOS</access_scope>
<coherent_access>false</coherent_access>
<ordered_access>false</ordered_access>
</presentation>
<partition>
<name>
<element>ABC</element>
<element>DEF</element>
<element>GHI</element>
<element>JKL</element>
<element>MNO</element>
<element>PQR</element>
<element>STU</element>
<element>VW</element>
<element>XYZ</element>
</name>
</partition>
<!--group_data>
<value></value>
</group_data-->
<entity_factory>
<autoenable_created_entities>true</autoenable_created_entities>
</entity_factory>
</subscriber_qos>
<publisher_qos>
<presentation>
<access_scope>INSTANCE_PRESENTATION_QOS</access_scope>
<coherent_access>false</coherent_access>
<ordered_access>false</ordered_access>
</presentation>
<partition>
<name>
<element>XYZ</element>
<element>VW</element>
<element>STU</element>
<element>PQR</element>
<element>MNO</element>
<element>JKL</element>
<element>GHI</element>
<element>DEF</element>
<element>ABC</element>
</name>
</partition>
<!--group_data>
<value></value>
</group_data-->
<entity_factory>
<autoenable_created_entities>true</autoenable_created_entities>
</entity_factory>
</publisher_qos>
<topic_qos>
<!--topic_data>
<value></value>
</topic_data-->
<durability>
<kind>VOLATILE_DURABILITY_QOS</kind>
</durability>
<durability_service>
<service_cleanup_delay>
<sec>0</sec>
<nanosec>0</nanosec>
</service_cleanup_delay>
<history_kind>KEEP_LAST_HISTORY_QOS</history_kind>
<history_depth>1</history_depth>
<max_samples>LENGTH_UNLIMITED</max_samples>
<max_instances>LENGTH_UNLIMITED</max_instances>
<max_samples_per_instance>LENGTH_UNLIMITED</max_samples_per_instance>
</durability_service>
<deadline>
<period>
<sec>DURATION_INFINITE_SEC</sec>
<nanosec>DURATION_INFINITE_NSEC</nanosec>
</period>
</deadline>
<latency_budget>
<duration>
<sec>0</sec>
<nanosec>0</nanosec>
</duration>
</latency_budget>
<liveliness>
<kind>AUTOMATIC_LIVELINESS_QOS</kind>
<lease_duration>
<sec>DURATION_INFINITE_SEC</sec>
<nanosec>DURATION_INFINITE_NSEC</nanosec>
</lease_duration>
</liveliness>
<reliability>
<kind>BEST_EFFORT_RELIABILITY_QOS</kind>
<max_blocking_time>
<sec>0</sec>
<nanosec>100000000</nanosec>
</max_blocking_time>
</reliability>
<destination_order>
<kind>BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS</kind>
</destination_order>
<history>
<kind>KEEP_LAST_HISTORY_QOS</kind>
<depth>1</depth>
</history>
<resource_limits>
<max_samples>LENGTH_UNLIMITED</max_samples>
<max_instances>LENGTH_UNLIMITED</max_instances>
<max_samples_per_instance>LENGTH_UNLIMITED</max_samples_per_instance>
</resource_limits>
<transport_priority>
<value>0</value>
</transport_priority>
<lifespan>
<duration>
<sec>DURATION_INFINITE_SEC</sec>
<nanosec>DURATION_INFINITE_NSEC</nanosec>
</duration>
</lifespan>
<ownership>
<kind>SHARED_OWNERSHIP_QOS</kind>
</ownership>
</topic_qos>
</qos_profile>
</dds>