1

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

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

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

作为 CORBA ORB 一部分的所有 IDL 编译器都会生成大量 CORBA 特定的代码和样板。我想要一些从 IDL 到 C++/Java/等的简单映射的东西。例如,如果我有这个 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();
  };
};
4

3 回答 3

2

您可以使用该local interface支持,从而生成一个具有纯虚拟方法的 C++ 基类来实现。例如,LwCCM 使用它来定义组件,例如AXCIOMA,我们使用本地接口与 IDL 中定义的数据相结合。有关更多信息,请参阅我们的一篇文章。

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

于 2021-03-03T08:04:37.703 回答
1

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

对于其他 DDS 实现,我不能像 OpenDDS 那样多说,但我知道 Connext 的这个支持页面说它们也不支持接口。它确实说他们支持valuetype,这有点像 an interface,但他们将其视为 astruct并忽略对它们的操作。

于 2021-03-03T03:53:42.860 回答
1

有一个名为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;
   }
于 2021-03-03T15:53:58.210 回答