DDS IDL 编译器

问题描述

我正在使用 IDL 为使用 OpenDDS 的应用程序定义数据。

我也想使用 IDL 来定义应用程序的接口,但 OpenDDS(和大多数其他 DDS 实现)不支持 IDL 中的接口。

是否有任何编译器可以从 IDL 接口生成简单的存根?我需要它至少支持 C++ 和 Java。

作为 CORBA ORB 一部分的所有 IDL 编译器都会生成大量特定于 CORBA 的代码和样板。我想要一些从 IDL 到 C++/Java/etc 的简单映射。例如,如果我有这个 IDL:

module sample_module {
  interface sample_interface {
    attribute char sample_field;
    boolean sample_func();
  };
};

我希望编译器在 C++ 中生成这样的文件

namespace sample_module {
  class sample_interface {
    char sample_field;
    boolean sample_func();
  };
};

解决方法

在 DDS 规范的 IDL 中的接口之外,据我所知,DDS 本身并没有使用接口。它总是将自己的 IDL 限制为 CORBA 的一个子集。因此,除了使用 tao_idl 已经附带的支持之外,OpenDDS 不支持用户定义的接口。可以由 opendds_idl 生成的可选 C++11 映射没有您想要的所有 CORBA 样板,但它目前不支持接口。我认为 Java 映射仅支持 OpenDDS 基于 JNI 的特定情况。即使使用 TAO 的 C++ 映射,OpenDDS 也不支持使用 interface 类型作为 DDS 主题类型或内部。

我不能像对 OpenDDS 那样多说其他 DDS 实现,但我知道 this support page for Connext 说它们也不支持接口。它确实说他们支持 valuetype,这有点像 interface,但他们将其视为 struct 并忽略对它们的操作。

,

您可以使用 local interface 支持,这会生成带有纯虚拟方法的 C++ 基类来实现。例如,这被 LwCCM 用于定义组件,例如参见 AXCIOMA,我们使用本地接口与 IDL 中定义的数据相结合。有关更多信息,请参阅我们的 articles 之一。

作为替代方案,您也可以基于 IDL 创建自己的自定义生成,在 TAOX11/AXCIOMA/R2CORBA 中,我们使用的是 RIDL,您可以创建自定义后端生成一些特定于接口的代码

,

有一个名为 Remote Procedure Call over DDS(RPC over DDS)的 OMG 标准,它定义了 IDL 接口如何映射到代码(它属于 DDS 标准系列)。 CoreDX DDS 确实为多种目标语言(包括 C++、Java 和 C#)支持此标准。

除了简单地将接口映射到目标语言之外,RPC over DDS 标准还提供了一种使用 DDS 作为 RPC 操作的底层传输的方法。它提供低级接口(即手动处理发送接收请求)和高级(调用“接口”方法)API。在任何一种情况下,进程间通信都是通过 DDS 以可互操作的方式处理的。在我看来,这是一种非常强大的方法。

以下是一些 IDL 示例:

module robot {
  exception TooFast {};
  enum Command { START_COMMAND,STOP_COMMAND,TERMINATE_COMMAND };
  struct Status 
  {
    string msg;
  };
  @DDSService
  interface RobotControl 
   {
     void  command(Command com);
     float setSpeed(float speed) raises (TooFast);
     float getSpeed();
     void  getStatus(out Status status); 
  };
}; 

注意:“@DDSService”注释通知有意识的 IDL 编译器为接口生成 RPC over DDS 支持。

如果没有@DDSService 注释,我们的代码生成器将简单地生成一个类声明[我认为您正在寻找],如下所示:

class RobotControl {
  public:
    RobotControl();
    ~RobotControl();

  public:
    virtual void                 command (
                                 /* IN    */  const enum robot::Command   com ) = 0;
    virtual float                setSpeed (
                                 /* IN    */  const float  speed ) = 0;
    virtual float                getSpeed ( ) = 0;
    virtual void                 getStatus (
                                 /* OUT   */  struct robot::Status & status ) = 0;

};

通过@DDSService 注释,生成了更多代码,提供完整的客户端实现 (robot.RobotControlClient) 和准备实现的抽象服务器端 (robot.RobotControlService)。有了它,您的客户端应用程序可以简单地执行以下操作:

RobotControlClient robotClient = new RobotControlClient( client_params );
robotClient.setSped( 10 );

服务器应用程序可以扩展robot.RobotControlService,并实现服务调用,如下所示:

public class MyRobotControlService  extends RobotControlService {
   ....
   private static final float MAX_SPEED = (float)20.0;

   public float                       
   setSpeed ( /* in    */ float speed ) throws TooFast
   {
     float retval = (float)0.0;
     if (speed < MAX_SPEED)
       {
         current_speed = speed;
         retval = this.current_speed;
       }
     else
       {
         /* EXCEPTION: */
         throw new robot.TooFast();
         /* not reached... */
       }
     return retval;
   }