2011-03-03 57 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

相關問題