Search code examples
c++compatibilitycorba

Using different incompatible versions of a CORBA Interface in the same app/module?


Given two IDL definitions: (I'm only implementing a client, the server side is fixed.)

// 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();
    // ...
  }
};

(Edit Note: added Foo3 method that cannot be overloaded because the return type changed.)

Is it somehow possible to compile both stub code files in the same C++ CORBA Client App?

Using the defaults of an IDL compiler, the above two IDL definitions will result in stub code that cannot be compiled into the same C++ module, as you'd get multiple definition errors from the linker. The client however needs to be able to talk to both server versions.

What are possible solutions?

(Note: We're using omniORB)


Solution

  • (Adding answer from one Stefan Gustafsson, posted in comp.object.corba 2011-03-08)


    If you look at it as a C++ problem instead of a CORBA problem, the solution is C++ namespaces. You could try to wrap the different implementations in different C++ namespaces. Like:

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

    And to be able to compile the C++ proxy/stub code you need to create C++ main files like:

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

    This will prevent the C++ linker complaining since the names will be different. Of course you could run into problems with C++ compilers not supporting nested namespaces..

    A second solution is to implement the invocation using DII, you could write a C++ class

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

    By using DII you can create any invocation you like, and can keep full control of your client code.


    I think this is a good idea, but I haven't been able to try it out yet, so there may lurk some unexpected surprises wrt to things no longer being in the global namespace.