1、创建简单示例程序
在这里,先建立一个IDL文件,然后通过使用Fast DDS-Gen生成程序生成这个简单示例程序。Fast DDS-Gen程序的编译安装请参考《Fast DDS入门二、Fast DDS在Windows平台的编译安装》,Fast DDS-Gen程序的使用请参考《Fast DDS入门四、Fast DDS-Gen使用介绍》。
(1)创建IDL文件
先建立一个单独的目录HelloWorldExample,在该目录下建立IDL文件和生成示例程序的c++源程序文件。
本示例构建最小的应用程序,必须通过IDL文件定义Topic。在本例中,IDL定义的Topic数据类型只是一个字符串消息。在首选文本编辑器中,创建具有以下内容的HelloWorld.IDL文件,并将其保存在HelloWorldExample目录中。
// HelloWorld.IDL
struct HelloWorld
{
string message;
};
(2)Fast DDS-Gen生成示例程序源码
然后,将此文件转换为Fast DDS能够理解的内容。为此,使用Fast DDS Gen代码生成工具,它可以执行生成示例的操作。执行如下命令:
fastddsgen.bat -example CMake HelloWorld.IDL
执行命令成功结束后,会产生一系列源文件,如下所示:
(3)CMake配置生成vs解决方案
Fast DDS-Gen生成示例程序源码后,生成了系列的.h、.cxx源文件,同时生成了CMakeLists.txt文件。因此可以通过CMake配置示例程序的依赖项目生成vs解决方案,然后通过vs编译生成可执行程序。相关依赖项的编译生成可参考《Fast DDS入门二、Fast DDS在Windows平台的编译安装》,以下为CMake界面程序的配置参考:
Configure和generate成功后,在out子目录下生成了项目、解决方案等文件,在out目录下可看到如下:
2、示例代码分析及编译运行
用vs打开CMake生成的generated_code.sln解决方案,如下图所示:
可以看到有4个项目,其中源码项目是:HelloWorld_lib和HelloWorld项目。HelloWorld_lib项目包含IDL生成的结构体类HelloWorld.h和HelloWorld.cxx,这个项目生成lib静态库。HelloWorld项目,依赖于HelloWorld_lib项目,可生成发布/订阅可执行程序。
(1)源代码分析
HelloWorld_lib项目的HelloWorld类,主要实现了IDL定义结构体类型的序列化和反序列化,头文件简要如下:
class HelloWorld
{
public:
/*!
* @brief This function serializes an object using CDR serialization.
* @param cdr CDR serialization object.
*/
eProsima_user_DllExport void serialize(
eprosima::fastcdr::Cdr& cdr) const;
/*!
* @brief This function deserializes an object using CDR serialization.
* @param cdr CDR serialization object.
*/
eProsima_user_DllExport void deserialize(
eprosima::fastcdr::Cdr& cdr);
private:
std::stringm_message;
};
HelloWorld项目的HelloWorldPubSubType类是HelloWorld类的封装类,其继承自TopicDataType类,该类可注册到Fast DDS中,序列化和反序列化函数是vitual函数在父类中声明,在子类中实现,在发布订阅函数中实现回调处理,发布时将HelloWorld类序列化并通过socket发送,订阅时通过socket接收到二进制后执行HelloWorld类的反序列化,以下为HelloWorldPubSubType类的核心代码:
bool HelloWorldPubSubType::serialize( //序列化函数
void* data,
SerializedPayload_t* payload)
{
HelloWorld* p_type= static_cast<HelloWorld*>(data);
// Object that manages the raw buffer.
eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast<char*>(payload->data), payload->max_size);
// Object that serializes the data.
eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN,eprosima::fastcdr::Cdr::DDS_CDR);
payload->encapsulation= ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;
// Serialize encapsulation
ser.serialize_encapsulation();
try
{
// Serialize the object.
p_type->serialize(ser);
}
catch(eprosima::fastcdr::exception::NotEnoughMemoryException& /*exception*/)
{
return false;
}
// Get the serialized length
payload->length= static_cast<uint32_t>(ser.getSerializedDataLength());
return true;
}
bool HelloWorldPubSubType::deserialize( //反序列化函数
SerializedPayload_t* payload,
void* data)
{
try
{
//Convert DATA to pointer of your type
HelloWorld* p_type= static_cast<HelloWorld*>(data);
// Object that manages the raw buffer.
eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast<char*>(payload->data), payload->length);
// Object that deserializes the data.
eprosima::fastcdr::Cdr deser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN,eprosima::fastcdr::Cdr::DDS_CDR);
// Deserialize encapsulation.
deser.read_encapsulation();
payload->encapsulation= deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;
// Deserialize the object.
p_type->deserialize(deser);
}
catch(eprosima::fastcdr::exception::NotEnoughMemoryException& /*exception*/)
{
return false;
}
return true;
}
HelloWorld项目的发布订阅类分别是:HelloWorldPublisher类和HelloWorldSubscriber类。发布类的核心源码有两个重要的成员函数,初始化函数init()和发送数据函数run(),代码如下所示:
bool HelloWorldPublisher::init() //初始化函数
{
/* Initialize data_ here */
//CREATE THE PARTICIPANT
DomainParticipantQos pqos;
pqos.name("Participant_pub");
participant_ = DomainParticipantFactory::get_instance()->create_participant(0, pqos);
if(participant_ == nullptr)
{
return false;
}
//REGISTER THE TYPE
type_.register_type(participant_);
//CREATE THE PUBLISHER
publisher_ = participant_->create_publisher(PUBLISHER_QOS_DEFAULT, nullptr);
if(publisher_ == nullptr)
{
return false;
}
//CREATE THE TOPIC
topic_ = participant_->create_topic(
"HelloWorldTopic",
type_.get_type_name(),
TOPIC_QOS_DEFAULT);
if (topic_== nullptr)
{
return false;
}
// CREATE THE WRITER
writer_ = publisher_->create_datawriter(topic_,DATAWRITER_QOS_DEFAULT, &listener_);
if(writer_ == nullptr)
{
return false;
}
std::cout << "HelloWorld DataWriter created." << std::endl;
return true;
}
发布者的初始化函数,首先创建参与者participant,参与者participant是publisher和subscriber的容器,可用来创建发布者和订阅者。之后参与者注册HelloWorld的数据类型,创建publisher,创建topic主题,最后通过发布者publisher创建写入器writer,通过writer可直接发送数据。
void HelloWorldPublisher::run() //运行函数发送数据
{
std::cout << "HelloWorld DataWriter waiting forDataReaders." << std::endl;
while(listener_.matched == 0)
{
std::this_thread::sleep_for(std::chrono::milliseconds(250)); // Sleep 250 ms
}
// Publication code
HelloWorld st;
/* Initialize your structure here */
int msgsent= 0;
char ch = 'y';
do
{
if (ch == 'y')
{
writer_->write(&st);
++msgsent;
std::cout << "Sendingsample, count=" << msgsent << ", sendanother sample?(y-yes,n-stop): ";
}
else if (ch == 'n')
{
std::cout << "Stoppingexecution " << std::endl;
break;
}
else
{
std::cout << "Command" << ch << " notrecognized, please enter \"y/n\":";
}
} while(std::cin >> ch);
}
发送数据函数通过publisher的写入器writer直接发送HelloWorld类型的数据st。
订阅类的核心源码也有两个重要的成员函数,初始化函数init()和其订阅监听器子类成员函数SubListener::on_data_available(),Init()成员函数雷同于publisher的init()成员函数,只不过是subscriber的init()函数是建立订阅者subscriber和监听器listener,通过监听器回调接收订阅的数据。
监听器SubListener::on_data_available()数据接收代码如下所示:
void HelloWorldSubscriber::SubListener::on_data_available( //监听接收数据函数
DataReader* reader)
{
// Take data
HelloWorld st;
SampleInfo info;
if (reader->take_next_sample(&st,&info) == ReturnCode_t::RETCODE_OK)
{
if(info.valid_data)
{
// Printyour structure data here.
++samples;
std::cout << "Samplereceived, count=" << samples << std::endl;
}
}
}
on_data_available()函数,是监听器的回调函数,被订阅者subscriber的阅读器reader接收到数据后,将socket接收的二进制数据反序列化成HelloWorld类数据,是开发人员的订阅接收数据入口。
(2)编译运行可执行程序
在vs开发工具中执行build命令,将在out/debug或release目录下生成可执行二进制文件HelloWorld.exe,同时将其依赖的库文件也拷贝到这里。如下所示:
然后通过powershell执行两个HelloWorld.exe命令,第一个命令后面空格后输入subscriber字符,第二个命令后面空格后输入publisher字符,发布程序和订阅程序将能够正常运行。运行界面如下所示:
至此,Fast DDS的简单发布订阅示例程序的创建、编译、运行就成功结束了。
CSDN下载:免费下载Fast DDS简单发布订阅示例程序源码文章来源:https://www.toymoban.com/news/detail-603865.html
github下载:git clone https://github.com/FantasticSaltedFish/Fast-DDS.git文章来源地址https://www.toymoban.com/news/detail-603865.html
到了这里,关于Fast DDS入门五、在Windows平台创建一个简单的Fast DDS示例程序的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!