2.1 使用DCPS


所有源代码可以在$DDS_ROOT/DevGuideExamples/DCPS/Messenger/ 目录下。额外的 DDS 和 DCPS功能在后面的章节中讨论。


2.1.1 定义数据类型

    DDS使用的每个数据类型都是使用 idl 定义的。OpenDDS 使用 #pragma指令来确定 dds 传输和处理的数据类型。这些数据类型由TAO IDL编译器和 OpenDDS  IDL编译器生成必要的代码来使用 OpenDDS 传输这些类型的数据。下面是定义我们的消息的 idl 文件数据类型:



module Messenger {

 #pragma DCPS_DATA_TYPE "Messenger::Message"
 #pragma DCPS_DATA_KEY "Messenger::Message subject_id"


   struct Message {
     string from;
     string subject;
     long subject_id;
     string text;
     long   count;
   };
 };


  DCPS_DATA_TYPE 杂注标记用于 OpenDDS 的数据类型。完全作用域的类型名称必须与此杂注一起使用。OpenDDS 要求数据类型为结构。该结构可能包含标量类型 (短、长、浮点等)、枚举、字符串序列、数组、结构和联合。本示例定义的结构Message在 OpenDDS 示例中使用的 messenger 模块。
    DCPS_DATA_KEY 杂注标识了 DCPS 数据类型的字段, 用作此类型键(key)。数据类型可能有零个或多个键。这些键用于标识不同的主题中的实例。每个键都应是数字或枚举类型、字符串或这些类型之一的 typedef. 1杂注被传递的完全作用域类型和成员标识该类型的键的名称。多个键用分别的DCPS_DATA_KEY 杂住。在上面的例子中, 我们确定了 Messenger::Message的subject_id 成员作为一个键。每个以唯一的 subject_id 值发布的示例都将定义为属于同一主题中的不同实例。由于我们使用默认 qos 策略, 具有相同 subject_id 值的后续示例被视为该实例的替换值。(最后一句话是什么意思呢,主要怎么用,还不是很明白)


2.1.2 处理IDL


    OpenDDS IDL首先由 TAO IDL 编译器处理。


    tao_idl Messenger.idl


    此外, 我们需要用 OpenDDS idl 编译器处理 idl 文件, 以生成OpenDDS 需要marshal和 demarshal 的Message的序列化和键支持代码,以及数据读取者和写入者的类型支持代码。此 idl编译器位于 $ DDS_ROOT/bin/ 并为每个被处理的 idl 文件生成三文件。三文件都以原始的 idl 文件名开头, 并显示为如下




  •  <filename>TypeSupport.idl
  • <filename>TypeSupportImpl.h
  • <filename>TypeSupportImpl.cpp

例如, 运行 opendds_idl 如下


opendds_idl Messenger.idl


    生成 MessengerTypeSupport. idl、MessengerTypeSupportImpl 和MessengerTypeSupportImpl.cpp. idl 文件,IDL文件包含 MessageTypeSupport,MessageDataWriter 和 MessageDataReader 接口定义。这些类型特定我们以后使用的 dds 接口在域中注册我们的数据类型, 发布示例的数据类型, 并接收已发布的示例。实现文件包含这些接口的实现。生成的 idl 文件本身应该用
用于生成存根和骨架的道 idl 编译器。这些和实现文件应与使用Message类型的 OpenDDS 应用程序链接。opendds idl 编译器有许多专门用于生成的代码的选项。这些选项在第8章所述。
    通常, 您不直接调用TAO或 OpenDDS idl 编译器如上所述, 但让您的构建环境是为您做的。使用 mpc 时, 整个过程被简化,从 dcpsexe_with_tcp 项目继承。这里是共同的 mpc 文件部分发布服务器和订阅服务器


project(*idl): dcps { 

// This project ensures the common components get built first. 

TypeSupport_Files { 

Messenger.idl 

} 

custom_only = 1 

}


DCPS 父项目添加支持自定义生成规则的类型。typesupport_files部分告诉 mpc 从信使生成Message类型支持文件从Messager.idl
使用 OpenDDS idl 编译。以下是发布者部分:


project(*Publisher): dcpsexe_with_tcp {
 exename = publisher
 after += *idl
 TypeSupport_Files {
 Messenger.idl
 }
 Source_Files {
 Publisher.cpp
 }
 }


dcpsexe_with_tcp项目链接DCPS库。


为完整起见, 这里是 mpc 文件的订阅部分:


project(*Subscriber): dcpsexe_with_tcp {
 exename = subscriber
 after += *idl
 TypeSupport_Files {
 Messenger.idl
 }
 Source_Files {
 Subscriber.cpp
 DataReaderListenerImpl.cpp
 }
 }


2.1.3 一个简单的Message发布者


    在本节中, 我们将介绍设置简单 OpenDDS 发布者所涉及的步骤过程.该代码分为逻辑部分, 并解释为我们提出的每一节。
我们省略了代码中一些无趣的部分 (如 # 包含指令, 错误处理和进程同步)。此示例发布服务器的完整源代码中的 Publisher.cpp 和 Writer.cpp 文件中找到$DDS_ROOT/DevGuideExamples/DCPS/Messenger/.

2.1.3.1 初始化参与者


main () 的第一部分将当前进程初始化为 OpenDDS 参与者




int main (int argc, char *argv[]) {
 try {
 DDS::DomainParticipantFactory_var dpf =
 TheParticipantFactoryWithArgs(argc, argv);
 DDS::DomainParticipant_var participant =
 dpf->create_participant(42, // domain ID
 PARTICIPANT_QOS_DEFAULT,
 0, // No listener required
 OpenDDS::DCPS::DEFAULT_STATUS_MASK);
 if (!participant) {
 std::cerr << "create_participant failed." << std::endl;
 return 1;
 }


TheParticipantFactoryWithArgs 宏在 Service_Participant.h中定义。并使用命令行参数初始化域参与者工厂。这些命令行参数用于初始化 OpenDDS 服务使用的 orb以及服务本身。这允许我们在命令行上传递 ORB_init () 选项以及形如 -DCPS*的OpenDDS 配置选项。可用的 OpenDDS 选项在7章中作了详细说明。
    create_participant () 操作使用域参与者工厂注册此进程作为由 id 42 指定的域中的参与者。参与者使用默认 qos 策略, 没有侦听器。使用 OpenDDS 默认状态掩码可确保所有相关的通信状态变化 (例如, 数据可用, 活泼丢失) 在中间件被传递到应用程序 (例如, 通过侦听器上的回调)。
    用户可以使用范围内的 id 定义任意数量的域 (0x0 ~ 0x7fffffff)。所有其他值由实现保留供内部使用。
    返回的域参与者对象引用然后用于注册我们的消息数据类型.