给定两个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)
发布于 2011-03-16 07:50:15
(添加Stefan Gustafsson的答案,张贴在comp.object.corba 2011-03-08中)
如果您把它看作是一个C++问题而不是一个C++问题,那么解决方案就是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的东西不再存在于全局名称空间中。
发布于 2011-03-03 11:40:07
我想到的是为每个版本将客户端代码分成不同的库。然后您可以根据要使用的版本选择正确的客户端。在最近的一个项目中,我们通过引入一个不依赖于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");https://stackoverflow.com/questions/5178031
复制相似问题