DDS IDL 编译器

DDS IDL Compiler

我正在使用 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++ 基础 class 具有要实现的纯虚拟方法。例如,LwCCM 使用它来定义组件,请参阅 AXCIOMA, there we use local interfaces combined with data defined in IDL. See one of our articles 了解更多信息。

作为替代方案,您还可以基于 IDL 创建自己的自定义生成,在 TAOX11/AXCIOMA/R2CORBA we are using RIDL 中,您可以创建自定义后端来生成一些特定于接口的代码

有一个名为 Remote Procedure Call over DDS (RPC over DDS) that defines how IDL interfaces can be mapped to code (it is in the family of DDS standards). CoreDX DDS 的 OMG 标准支持多种目标语言(包括 C++、Java 和 C#)的该标准。

除了简单地将接口映射到目标语言之外,RPC over DDS 标准还提供了一种使用 DDS 作为 RPC 操作的底层传输的方法。它提供低级接口(即处理手动发送接收请求)和高级接口(调用方法 'interface')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 声明 [我认为您正在寻找],看起来像这样:

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;
   }