基于OpenDDS开发发布订阅HelloMsg程序的过程(Windows)
基于OpenDDS的应用开发,主要分两个部分的工作:
(1)定义自己的IDL文件,并编译成消息数据类型通讯动态库;
(2)分别编写pub和sub程序,运行
具体步骤,有以下几个:
- 定义idl文件,如HelloMsg.ild
- 运行脚本,产生相应的消息类型符号导出头文件HelloMsgCommon_Export.h
- 编写mwc、mpc工作台和项目文件,如HelloMsg.mwc、HelloMsg.mpc
- 编译mpc文件,产生解决方案和工程,如HelloMsg.sln、HelloMsgCommon.vcxproj、HelloMsgPub.vcxproj、HelloMsgSub.vcxproj
- 编写HelloMsgPub.cpp和HelloMsgSub.cpp代码;
- 编译工程,产生动态库HelloMsgCommon.dll、HelloMsgPub.exe、HelloMsgSub.exe
- 运行发布和订阅程序,查看运行结果
下面,展开来看。。。
步骤一、定义HelloMsg.idl
module Hello
{#pragma DCPS_DATA_TYPE "Hello::HelloMsg"#pragma DCPS_DATA_KEY "Hello::HelloMsg msg"struct HelloMsg{string msg;};
};
步骤二、制作HelloMsg消息导出符号头文件HelloMsgCommon_Export.h
perl %ACE_ROOT%/bin/generate_export_file.pl HelloMsgCommon > HelloMsgCommon_Export.h
步骤三、定义HelloMsg.mwc、HelloMsg.mpc
workspace {// the -relative and -include cmdlines make it so this workspace // does not have to be in the $DDS_ROOT directory tree.// tell MPC to substitute our DDS_ROOT environment variables for relative pathscmdline += -relative DDS_ROOT=$DDS_ROOT// tell the projects where to find the DDS base projects (*.mpb)cmdline += -include $DDS_ROOT/MPC/config}
project(*Common) : dcps {sharedname = HelloMsgCommondynamicflags = HELLOMSGCOMMON_BUILD_DLLlibout = .requires += tao_orbsvcsrequires += no_opendds_safety_profileafter += Svc_Utilsincludes += $(TAO_ROOT)/orbsvcsidlflags += -I$(TAO_ROOT)/orbsvcs \-Wb,export_macro=HelloMsgCommon_Export \-Wb,export_include=HelloMsgCommon_Export.hdcps_ts_flags += -Wb,export_macro=HelloMsgCommon_ExportTypeSupport_Files {HelloMsg.idl}IDL_Files {HelloMsgTypeSupport.idlHelloMsg.idl}// We only want the generated filesHeader_Files {}// We only want the generated filesSource_Files {}
}project(HelloMsgPub) : dcpsexe, dcps_tcp, svc_utils {after += *Commonexename = HelloMsgPubrequires += tao_orbsvcsrequires += no_opendds_safety_profileincludes += $(TAO_ROOT)/orbsvcslibs += HelloMsgCommonIDL_Files {}TypeSupport_Files {}Header_Files {}Source_Files {HelloMsgPub.cpp}Documentation_Files {dds_tcp_conf.inidds_udp_conf.ini}
}project(HelloMsgSub) : dcpsexe, dcps_tcp {after += *Commonexename = HelloMsgSubrequires += tao_orbsvcsrequires += no_opendds_safety_profileincludes += $(TAO_ROOT)/orbsvcslibs += HelloMsgCommonTypeSupport_Files {}IDL_Files {}Header_Files {}Source_Files {HelloMsgSub.cpp}Documentation_Files {dds_tcp_conf.inidds_udp_conf.ini}
}
步骤四,产生vs2010的工程文件
perl %ACE_ROOT%/bin/mwc.pl -type vc10 HelloMsg.mwc产生HelloMsg.sln、HelloMsg_Common.vcxproj、HelloMsgPub.vcxproj和HelloMsgSub.vcxproj
步骤五、编写HelloMsgPub.cpp和HelloMsgSub.cpp代码
HelloMsgPub.cpp
/****************************************************************** file: HelloMsgPub.cpp* desc: Provides a simple C++ 'hello world' DDS publisher.* This publishing application will send data* to the example 'hello world' subscribing * application (hello_sub).* ****************************************************************/
#include <dds/DCPS/Service_Participant.h>
#include <dds/DCPS/Marked_Default_Qos.h>
#include <dds/DCPS/PublisherImpl.h>
#include "dds/DCPS/StaticIncludes.h"
#include <ace/streams.h>
#include <orbsvcs/Time_Utilities.h>#include <stdio.h>
#include <string.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#include "HelloMsgTypeSupportImpl.h"/***************************************************************** main()** Perform OpenDDS setup activities:* - create a Domain Participant* - create a Publisher* - register the StringMsg data type* - create a Topic* - create a DataWriter * Write data****************************************************************/int main(int argc, char * argv[])
{DDS::DomainParticipant * domain;DDS::Publisher * publisher;DDS::Topic * topic;DDS::DataWriter * dw;Hello::StringMsg stringMsg;DDS::ReturnCode_t retval;DDS::DomainParticipantFactory *dpf = TheParticipantFactoryWithArgs(argc, argv);
if ( dpf == NULL )
{
printf("ERROR initializing domainParticipantFactory.\n");
return -1;
} /* create a DomainParticipant */domain = dpf->create_participant( 2, PARTICIPANT_QOS_DEFAULT, NULL, 0 );if ( domain == NULL ){printf("ERROR creating domain participant.\n");return -1;}/* create a Publisher */publisher = domain->create_publisher(PUBLISHER_QOS_DEFAULT, NULL, 0 );if ( publisher == NULL ){printf("ERROR creating publisher.\n");return -1;}/* Register the data type with the OpenDDS middleware. * This is required before creating a Topic with* this data type. */Hello::StringMsgTypeSupport *stringMsgTS = new Hello::StringMsgTypeSupportImpl();;retval = stringMsgTS->register_type( domain, "StringMsg" );if (retval != DDS::RETCODE_OK){printf("ERROR registering type: %s\n", "DDS_error(retval)");return -1;}/* Create a DDS Topic with the StringMsg data type. */topic = domain->create_topic("helloTopic", "StringMsg", TOPIC_QOS_DEFAULT, NULL, 0 );if ( topic == NULL ){printf("ERROR creating topic.\n");return -1;}/* Create a DataWriter on the hello topic, with* default QoS settings and no listeners.*/dw = publisher->create_datawriter( topic, DATAWRITER_QOS_DEFAULT, NULL, 0 );if (dw == NULL){printf("ERROR creating data writer\n");return -1;}/* Initialize the data to send. The StringMsg data type* has just one string member.* Note: Alwyas initialize a string member with* allocated memory -- the destructor will free * all string members. */stringMsg.msg = new char[1024];strcpy((char*)stringMsg.msg.in(), "Hello World from C++!");int counter = 1;Hello::StringMsgDataWriter* sm_dw = Hello::StringMsgDataWriter::_narrow(dw);while ( 1 ){sprintf((char*)stringMsg.msg.in(), "Hello World from OpenDDS C++! index=%d", counter);DDS::ReturnCode_t ret = sm_dw->write ( stringMsg, DDS::HANDLE_NIL ); printf("OpenDDS wrote a sample, index=%d\n", counter);fflush(stdout);if ( ret != DDS::RETCODE_OK)
{printf("ERROR writing sample\n");return -1;
}
#ifdef _WIN32Sleep(1000);
#elsesleep(1);
#endifcounter++;}/* Cleanup */retval = domain -> delete_contained_entities();if ( retval != DDS::RETCODE_OK )printf("ERROR (%s): Unable to cleanup DDS entities\n","DDS_error(retval)");dpf->delete_participant(domain);
TheServiceParticipant->shutdown();return 0;
}
HelloMsgSub.cpp
/****************************************************************** file: HelloMsgSub.cpp* desc: Provides a simple C++ 'Hello World' DDS subscriber.* This subscribing application will receive data* from the example 'hello world' publishing * application (hello_pub).* ****************************************************************/
#include <dds/DCPS/Service_Participant.h>
#include <dds/DCPS/Marked_Default_Qos.h>
#include <dds/DCPS/PublisherImpl.h>
#include <ace/streams.h>
#include <orbsvcs/Time_Utilities.h>#include "dds/DCPS/StaticIncludes.h"#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#include "HelloMsgTypeSupportImpl.h"#ifdef _WIN32
# define SLEEP(a) Sleep(a*1000)
#else
# define SLEEP(a) sleep(a);
#endifint all_done = 0;/***************************************************************** Construct a DataReaderListener and override the * on_data_available() method with our own. All other* listener methods will be default (no-op) functions.****************************************************************/
class SubListener : public DDS::DataReaderListener
{
public:void on_data_available( DDS::DataReader * dr );void on_requested_deadline_missed (DDS::DataReader_ptr reader,const DDS::RequestedDeadlineMissedStatus & status);void on_requested_incompatible_qos (DDS::DataReader_ptr reader,const DDS::RequestedIncompatibleQosStatus & status);void on_liveliness_changed (DDS::DataReader_ptr reader,const DDS::LivelinessChangedStatus & status);virtual void on_subscription_matched (DDS::DataReader_ptr reader,const DDS::SubscriptionMatchedStatus & status);void on_sample_rejected(DDS::DataReader_ptr reader,const DDS::SampleRejectedStatus& status);void on_sample_lost(DDS::DataReader_ptr reader,const DDS::SampleLostStatus& status);
};/***************************************************************** DataReader Listener Method: on_data_avail()** This listener method is called when data is available to* be read on this DataReader.****************************************************************/
void SubListener::on_data_available( DDS::DataReader * dr)
{Hello::StringMsgSeq samples;DDS::SampleInfoSeq samples_info;DDS::ReturnCode_t retval;DDS::SampleStateMask ss = DDS::ANY_SAMPLE_STATE;DDS::ViewStateMask vs = DDS::ANY_VIEW_STATE;DDS::InstanceStateMask is = DDS::ANY_INSTANCE_STATE;/* Convert to our type-specific DataReader */Hello::StringMsgDataReader* reader = Hello::StringMsgDataReader::_narrow( dr );/* Take any and all available samples. The take() operation* will remove the samples from the DataReader so they* won't be available on subsequent read() or take() calls.*/retval = reader->take( samples, samples_info,
DDS::LENGTH_UNLIMITED,
ss,
vs,
is );if ( retval == DDS::RETCODE_OK ){/* iterrate through the samples */
for ( unsigned int i = 0;i < samples.length(); i++)
{/* If this sample does not contain valid data,* it is a dispose or other non-data command,* and, accessing any member from this sample * would be invalid.*/if ( samples_info[i].valid_data)printf("OpenDDS received a sample, No=%d/%d, [%s]\n", i, samples.length(), samples[i].msg.in());
}fflush(stdout);/* read() and take() always "loan" the data, we need to* return it so OpenDDS can release resources associated* with it. */reader->return_loan( samples, samples_info );}else{printf("ERROR (%s) taking samples from DataReader\n","DDS_error(retval)");}
}void SubListener::on_requested_deadline_missed (
DDS::DataReader_ptr reader,
const DDS::RequestedDeadlineMissedStatus & status)
{printf("ERROR (%s) on_requested_deadline_missed\n","DDS_error(retval)");
}void SubListener::on_requested_incompatible_qos (
DDS::DataReader_ptr reader,
const DDS::RequestedIncompatibleQosStatus & status)
{
printf("ERROR (%s) on_requested_incompatible_qos\n",
"DDS_error(retval)");
}void SubListener::on_liveliness_changed (
DDS::DataReader_ptr reader,
const DDS::LivelinessChangedStatus & status)
{
printf("ERROR (%s) on_liveliness_changed\n",
"DDS_error(retval)");
}void SubListener::on_subscription_matched (
DDS::DataReader_ptr reader,
const DDS::SubscriptionMatchedStatus & status
)
{
printf("ERROR (%s) on_subscription_matched\n",
"DDS_error(retval)");
}void SubListener::on_sample_rejected(
DDS::DataReader_ptr reader,
const DDS::SampleRejectedStatus& status
)
{
printf("ERROR (%s) on_sample_rejected\n",
"DDS_error(retval)");
}void SubListener::on_sample_lost(
DDS::DataReader_ptr reader,
const DDS::SampleLostStatus& status
)
{
printf("ERROR (%s) on_sample_lost\n",
"DDS_error(retval)");
}/***************************************************************** main()** Perform OpenDDS setup activities:* - create a Domain Participant* - create a Subscriber* - register the StringMsg data type* - create a Topic* - create a DataReader and attach the listener created above* And wait for data****************************************************************/#if defined(__vxworks) && !defined(__RTP__)
int hello_sub(char * args)
#else
int main(int argc, char * argv[])
#endif
{DDS::DomainParticipant * domain;DDS::Subscriber * subscriber;DDS::Topic * topic;DDS::DataReader * dr;SubListener drListener;DDS::ReturnCode_t retval;/* Get an instance of the DDS DomainPartiticpantFactory -- * we will use this to create a DomainParticipant.*/DDS::DomainParticipantFactory *dpf = TheParticipantFactoryWithArgs(argc, argv);
if ( dpf == NULL )
{
printf("ERROR initializing domainParticipantFactory.\n");
return -1;
} /* create a DomainParticipant */domain = dpf->create_participant( 2, PARTICIPANT_QOS_DEFAULT, NULL, 0 );if ( domain == NULL ){printf("ERROR creating domain participant.\n");return -1;}/* create a Subscriber */subscriber = domain->create_subscriber(SUBSCRIBER_QOS_DEFAULT,
NULL,
0 );if ( subscriber == NULL ){printf("ERROR creating subscriber\n");return -1;}/* Register the data type with the OpenDDS middleware. * This is required before creating a Topic with* this data type. */Hello::StringMsgTypeSupport *stringMsgTS = new Hello::StringMsgTypeSupportImpl();;retval = stringMsgTS->register_type( domain, "StringMsg" );if (retval != DDS::RETCODE_OK){printf("ERROR registering type: %s\n", "DDS_error(retval)");return -1;}/* create a DDS Topic with the StringMsg data type. */topic = domain->create_topic( "helloTopic",
"StringMsg",
TOPIC_QOS_DEFAULT,
NULL,
0 );if ( ! topic ){printf("ERROR creating topic\n");return -1;}/* create a DDS_DataReader on the hello topic (notice* the TopicDescription is used) with default QoS settings, * and attach our listener with our on_data_available method.*/dr = subscriber->create_datareader( (DDS::TopicDescription*)topic, DATAREADER_QOS_DEFAULT,&drListener, DDS::DATA_AVAILABLE_STATUS );if ( ! dr ){printf("ERROR creating data reader\n");return -1;}/* Wait forever. When data arrives at our DataReader, * our dr_on_data_avilalbe method will be invoked.*/while ( !all_done )SLEEP(30);/* Cleanup */retval = domain -> delete_contained_entities();if ( retval != DDS::RETCODE_OK )printf("ERROR (%s): Unable to cleanup DDS entities\n","DDS_error(retval)");dpf->delete_participant(domain);
TheServiceParticipant->shutdown();return 0;
}
步骤六、编译工程
打开HelloMsg.sln,产生动态库HelloMsg_Common.dll(.lib)和发布订阅程序HelloMsgPub.exe和HelloMsgSub.exe
步骤七、运行发布订阅程序
HelloMsgPub -ORBDebugLevel 0 -DCPSDebugLevel 0 -DCPSTransportDebugLevel 0 -DCPSConfigFile ../../etc/dds_udp_conf.ini -ORBLogFile publisher.log
OpenDDS wrote a sample, index=1
OpenDDS wrote a sample, index=2
OpenDDS wrote a sample, index=3
OpenDDS wrote a sample, index=4
OpenDDS wrote a sample, index=5
OpenDDS wrote a sample, index=6
OpenDDS wrote a sample, index=7
OpenDDS wrote a sample, index=8
OpenDDS wrote a sample, index=9
OpenDDS wrote a sample, index=10
HelloMsgSub -ORBDebugLevel 0 -DCPSDebugLevel 0 -DCPSTransportDebugLevel 0 -DCPSConfigFile ../../etc/dds_udp_conf.ini -ORBLogFile subscriber.log
OpenDDS received a sample, No=0/1, [Hello World from OpenDDS C++! index=1]
OpenDDS received a sample, No=0/1, [Hello World from OpenDDS C++! index=2]
OpenDDS received a sample, No=0/1, [Hello World from OpenDDS C++! index=3]
OpenDDS received a sample, No=0/1, [Hello World from OpenDDS C++! index=4]
OpenDDS received a sample, No=0/1, [Hello World from OpenDDS C++! index=5]
OpenDDS received a sample, No=0/1, [Hello World from OpenDDS C++! index=6]
OpenDDS received a sample, No=0/1, [Hello World from OpenDDS C++! index=7]
OpenDDS received a sample, No=0/1, [Hello World from OpenDDS C++! index=8]
OpenDDS received a sample, No=0/1, [Hello World from OpenDDS C++! index=9]
OpenDDS received a sample, No=0/1, [Hello World from OpenDDS C++! index=10]
基于OpenDDS开发发布订阅HelloMsg程序的过程(Windows)相关推荐
- 基于云开发的微信小程序:个人相册ByUestcXiye
基于云开发的微信小程序:个人相册ByUestcXiye 作业要求 第一次作业 第二次作业 结课作业 小程序开发入门 开发前的准备 注册微信小程序 新建一个模板小程序 开通云开发服务 第一次作业 参考资 ...
- 基于云开发的微信小程序实战教程(二)
基于云开发的微信小程序实战教程(二) 上篇文章中,简单介绍了下小程序云开发的概念,还有开发工具的安装和配置,云开发环境已经搭建完毕. 本章主要内容:微信开发者工具如何使用,小程序云开发的基础目录结构 ...
- vue.js反编译_基于electron-vue开发的微信小程序反编译客户端
开源一个小程序反编译客户端 咨询小程序反编译的同学比较多,虽然有开源库但是还是有同学不清楚如何去操作,所以索性做了一个客户端方便进行小程序的反编译 # 技术选型 网上已经有大佬实现了C#版的反编译工具 ...
- 完整的OpenDDS的发布订阅编写及源码(Windows)
一个完整的OpenDDS的发布订阅编写及源码,包括SimuMsg.idl.SimuMsg.mwc和SimuMsg.mpc,SimuMsgCommon_Export.h.publisher.cpp.su ...
- 基于Uniapp开发的MIPCMS小程序
基于Uniapp开发的MIPCMS小程序 介绍 很早就有想法把mipcms官方的小程序改了,结果一直拖到现在.最近有了一点空闲时间,简单改造下mipcms小程序. 软件架构 本软件后台采用mipcms ...
- 基于JavaSwing开发3D立体字制作程序 课程设计 大作业
基于JavaSwing开发3D立体字制作程序: (大作业) 开发环境: Windows操作系统 开发工具: Eclipse+Jdk 运行效果图: 基于JavaSwing开发3D立体字制作程序: ...
- 基于云开发的微信小程序实战教程(一)
基于云开发的微信小程序实战教程(一) 最近刚开发了款小程序,在开发过程中发现,基于云开发的教程资源不是很多,而且很不详细.所以边实战边总结了下云开发的简单教程,希望对你有所帮助. 本章主要内容:什么是 ...
- Eclipse中使用Hadoop集群模式开发配置及简单程序示例(Windows下)
Hadoop入门配置系列博客目录一览 1. Eclipse中使用Hadoop伪分布模式开发配置及简单程序示例(Linux下) 2. 使用Hadoop命令行执行jar包详解(生成jar.将文件上传到df ...
- 基于云开发创建(小程序云商城,基本页面的创建及动态代码的编写)
CSDN话题挑战赛第2期 参赛话题:万家争鸣的云计算修罗场 在这个专属于"云"的时代,各位云端弄潮儿们,请分享出你的云计算学习历程吧! 你可以从以下几个方面着手(不强制),或者根据 ...
最新文章
- 吴裕雄 10-MySQL插入数据
- 青春可长可短, 就看自己如何度过(亦或者如白驹过隙, 稍纵即逝 正所谓且行且珍惜)...
- jvm系列(九):如何优化Java GC
- 【qduoj - 1011】数组中出现最多的元素(巧妙方法 或 排序 或 map)
- redis内存模型及应用解读
- 初次使用Atlas JavaScript (Part 3 - 实现自己的应用)
- Centos7开放及查看端口
- sql server 群集_SQL Server 2014 –安装群集实例–分步(1/3)
- js高程笔记1-3章
- 开源大数据:openLookeng 虚拟化引擎
- FastDFS搭建文件服务器
- LINUX 内核调试基础+编程基础
- 渝粤题库 陕西师范大学 《教育科学研究方法》作业
- 【密码学原理与实践】(五)希尔密码
- 职场达人教你如何做高效工作汇报!
- bootstrap-selectpicker
- 计算机网络:网络传输介质
- oreo另一个意思_孑孓、仄亾、片爿…看起来天生一对的字,意思竟然大不同
- PCIe系列专题之三:3.0 数据链路层概述
- 树莓派lnmp安装mysql_在树莓派上搭建LNMP环境
热门文章
- java细粒度锁_Java细粒度锁实现的3种方式
- alert 回调_JavaScript中到底什么时候回调函数Callback
- java年利润编程题_[编程入门]利润计算-题解(Java代码)
- html table vtop,PART2HTML语言.doc
- leetcode167. 两数之和 II - 并没有那么easy的easy题
- C++(STL):14--- forward_list比list更高效的容器
- 大数据学习(09)--spark学习
- 两条边延长角会有什么变化_叶片锁是什么样的 叶片锁使用方法【详解】
- linux加密框架 crypto 算法管理 - 创建哈希算法实例
- 英语口语 week11 Friday