Использование разных несовместимых версий интерфейса CORBA в одном приложении / модуле? - PullRequest
1 голос
/ 03 марта 2011

С учетом двух определений IDL: (Я только реализую клиент, серверная сторона исправлена.)

// Version 1.2
module Server {
  interface IObject {
    void Foo1();
    void Foo2() raises(EFail);
    string Foo3();
    // ...
  }
};

// Version 2.3
module Server {
  interface IObject {
    // no longer available: void Foo1();
    void Foo2(string x) raises(ENotFound, EFail); // incompatible change
    wstring Foo3();
    // ...
  }
};

( Редактировать Примечание: добавлен метод Foo3, который не может быть перегружен из-за изменения типа возвращаемого значения.)

Возможно ли как-то скомпилировать оба файла-заглушки в одном клиентском приложении C ++ CORBA?

Используя значения по умолчанию компилятора IDL, два приведенных выше определения IDL приведут к заглушке кода, которая не может быть скомпилирована в один и тот же модуль C ++, поскольку вы получите несколько ошибок определения от компоновщика. Однако клиент должен иметь возможность общаться с обеими версиями сервера.

Каковы возможные решения?

(Примечание: мы используем omniORB )

Ответы [ 2 ]

2 голосов
/ 16 марта 2011

(Добавление ответа от одного Стефана Густафссона, опубликовано в comp.object.corba 2011-03-08)


Если вы рассматриваете это как проблему C ++ вместо проблемы CORBA, Решением является пространство имен C ++. Вы можете попробовать обернуть разные реализации в разные C ++ Пространства имен. Как:

namespace v1 {
#include "v1/foo.h" // From foo.idl version 1
}
namespace v2 {
#include "v2/foo.h" // from foo.idl version 2
}

И чтобы иметь возможность компилировать код прокси / заглушки C ++, вам нужно создать C ++ основные файлы, такие как:

// foo.cpp
namespace v1 {
#include "v1/foo_proxy.cpp"  // filename depend on IDL compiler
}
namespace v2 {
#include "v2/foo_proxy.cpp"
}

Это предотвратит жалобу компоновщика C ++, так как имена будут разные. Конечно ты могут возникнуть проблемы с компиляторами C ++, не поддерживающими вложенные Пространства имен ..

Вторым решением является реализация вызова с использованием DII, вы можете написать класс C ++

class ServerCall {
   void foo2_v1() {
       // create request
       // invoke
   }
   void foo2_v2(String arg) {
       // create_list
       // add_value("x",value,ARG_IN)
       // create_request
       // invoke
   }
}

Используя DII, вы можете создавать любые вызовы, которые вам нравятся, и можете сохранять полный контроль кода вашего клиента.


Я думаю, что это хорошая идея, но я пока не смог ее опробовать, поэтому могут возникнуть некоторые неожиданные сюрпризы в отношении вещей, которых больше нет в глобальном пространстве имен.

1 голос
/ 03 марта 2011

Что мне приходит в голову, так это разделение клиентского кода на отдельные библиотеки для каждой версии. Затем вы можете выбрать правильный клиент в зависимости от используемой версии. В недавнем проекте мы справились с этим, представив сервисный уровень без зависимости от CORBA IDL. Например:

class ObjectService
{
public:
 virtual void Foo1() = 0;
 virtual void Foo2() = 0;
 virtual void Foo2(const std::string &x) = 0;
};

Для каждой версии создайте класс, производный от ObjectService, и выполните операции с помощью вызывая CORBA :: Object. Каждый производный класс должен находиться в отдельной библиотеке.

В клиентской реализации вы работаете только с экземплярами ObjectService.

CORBA::Object_var remoteObject=... // How to get the remote object depends on your project
ObjectService *serviceObject=0;
// create a service object matching the remote object version
// Again, this is project specific
switch (getRemoteObjectVersion(remoteObject))
{
 case VERSION_1_2:
   serviceObject=new ServiceObjectImpl12(remoteObject);
   break;
 case VERSION_2_3:
   serviceObject=new ServiceObjectImpl23(remoteObject);
   break;
 default:
   // No matching version found, throw exception?
   break;
}

// Access remote object through service object
serviceObject->Foo2("42");
...