Компилятор DDS IDL

#java #c #idl #data-distribution-service #opendds

#java #c #idl #служба распространения данных #opendds

Вопрос:

Я использую IDL для определения данных для приложения с использованием OpenDDS.

Я также хочу использовать IDL для определения интерфейсов для приложения, но OpenDDS (и, похоже, большинство других реализаций DDS) не поддерживают интерфейсы в IDL.

Существуют ли какие-либо компиляторы, которые будут генерировать простые заглушки из интерфейсов IDL? Мне нужно, чтобы он поддерживал хотя бы C и Java.

Все компиляторы IDL, входящие в состав CORBA ORBs, генерируют много специфичного для 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();
  };
};
 

Ответ №1:

Вы могли бы использовать local interface поддержку, которая приводит к базовому классу C с чисто виртуальными методами для реализации. Это, например, используется LwCCM для определения компонентов, см., Например, AXCIOMA, там мы используем локальные интерфейсы в сочетании с данными, определенными в IDL. Смотрите одну из наших статей для получения дополнительной информации.

В качестве альтернативы вы также можете создать свою собственную пользовательскую генерацию на основе IDL, в TAOX11 / AXCIOMA / R2CORBA мы используем RIDL, вы можете создать пользовательский сервер для генерации некоторого кода, специфичного для интерфейсов

Комментарии:

1. Я думаю, что это единственное реальное решение. Я собираюсь попробовать написать бэкэнд для omniidl , потому что я лучше знаком с python.

2. Поддержка интерфейсов DDS определена в стандарте RPC поверх DDS. Более подробная информация в моем ответе.

Ответ №2:

Вне интерфейсов в IDL спецификаций DDS, сам DDS, насколько я знаю, не используется для интерфейсов. Он всегда ограничивает свой собственный IDL подмножеством CORBA. Из-за этого OpenDDS не поддерживает пользовательские интерфейсы за пределами поддержки, которая уже поставляется с using tao_idl . Необязательное отображение C 11, которое может быть сгенерировано, opendds_idl свободно от всех шаблонов CORBA, как вы хотите, но на данный момент оно не поддерживает интерфейсы. Я думаю, что отображение Java поддерживает их только для конкретной ситуации на основе OpenDDS на основе JNI. Даже при использовании сопоставления TAO с C OpenDDS не поддерживает использование interface типов в качестве типа темы DDS или внутри него.

Я не могу говорить так много о других реализациях DDS, как о OpenDDS, но я знаю, что на этой странице поддержки Connext говорится, что они также не поддерживают интерфейсы. В нем говорится, что они поддерживают valuetype , что-то вроде an interface , но они рассматривают его как a struct и игнорируют операции над ними.

Комментарии:

1. Это был вывод, к которому я тоже пришел. Я просто надеялся, что кто-то с большим опытом работы с IDL и DDS будет знать то, чего я не знал.

2. Поддержка интерфейсов DDS определена в стандарте RPC поверх стандарта DDS. Более подробная информация в моем ответе.

Ответ №3:

Существует стандарт OMG, называемый удаленным вызовом процедур через DDS (RPC через DDS), который определяет, как интерфейсы 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 через поддержку 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 amp; status ) = 0;

};
 

С аннотацией @DDSService генерируется намного больше кода, который обеспечивает полную реализацию на стороне клиента (robot.RobotControlClient) и абстрактная серверная часть, готовая к реализации (robot.RobotControlService). При этом ваше клиентское приложение может просто сделать это:

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

Серверное приложение может расширять робота.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;
   }