【问题标题】:Using different incompatible versions of a CORBA Interface in the same app/module?在同一个应用程序/模块中使用不同不兼容版本的 CORBA 接口?
【发布时间】:2011-03-03 07:55:49
【问题描述】:

给定两个 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

【问题讨论】:

    标签: c++ compatibility corba


    【解决方案1】:

    (添加来自一位 Stefan Gustafsson 的答案,发布于 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,您可以创建任何您喜欢的调用,并且可以保持完整 控制您的客户端代码。


    我认为这是个好主意,但我还没有尝试过,所以可能会因为不再位于全局命名空间中的东西而潜伏一些意想不到的惊喜。

    【讨论】:

      【解决方案2】:

      我想到的是将客户端代码拆分为每个版本的单独库。 然后您可以根据要使用的版本选择正确的客户端。 在最近的一个项目中,我们通过引入一个不依赖于 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");
      

      【讨论】:

      • “单独的库”是指单独的 DLL?
      • 是的,否则您会遇到您已经提到的相同编译/链接问题。当然,您必须将正确的 IDL 编译到每个 DLL 中。
      猜你喜欢
      • 1970-01-01
      • 2010-09-23
      • 1970-01-01
      • 1970-01-01
      • 2012-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多