2011-03-03 64 views
1

给定两个IDL的定义:(我只实现客户端,服务器端是固定的。)在同一个应用程序/模块中使用不同的不兼容版本的CORBA接口?

// 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

(添加从一个斯特凡·古斯塔夫森答案,张贴在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你可以创建你喜欢的任何调用,并能保持完全 控制的客户代码。


我认为这是一个好主意,但我一直没能尝试一下呢,所以有可能潜伏着一些意想不到的惊喜WRT的东西在全局命名空间不再。

1

什么在我脑海中会分裂客户端代码为每个版本单独的库。 然后,您可以根据要使用的版本选择正确的客户端。 在最近的一个项目中,我们通过引入一个不依赖于CORBA IDL的服务层来处理这个问题。 例如:

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

对于每个版本,创建ObjectService派生的类和 执行的操作调用CORBA ::对象。每个派生类必须位于单独的库中。

在客户端实现中,您只能对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"); 
+0

“分开的库”是指单独的DLL? – 2011-03-03 16:21:25

+0

是的,否则你遇到你已经提到的相同的编译/链接问题。当然,您必须将正确的IDL编译到每个DLL中。 – jopa 2011-03-03 17:50:04

相关问题