Slice到C++映射

按:本文是DPWI第6章的筆記。

 

客戶端Slice到C++映射定義的是:怎樣把Slice數據類型翻譯成C++類型,客戶怎樣調用操作、傳遞參數、處理錯誤。C++映射線程安全,不存在內存管理問題。不建議查看slice2cpp生成的C++映射文件,但建議掌握C++映射規則。

1、模塊映射 
module M{...}
映射爲
namespace M{...}

2、類型映射 
⑴基本類型
Slice     C++ 
bool   → bool
byte   → Ice::Byte
short  → Ice::Short
int    → Ice::Int
long   → Ice::Long
float  → Ice::Float
double → Ice::Double
string → std::string
 

⑵複雜類型 
Slice     C++ 
枚舉 →   枚舉
結構 →   結構,支持比較符,可用於Slice詞典鍵類型,支持深度複製、賦值。
序列 →   std::vector,可以映射爲list,dequeue,數組,範圍。
詞典 →   std::map。
 

3、異常映射 
異常可映射爲同名C++類,支持如下操作:
• ice_name  異常的名字。
• ice_clone 多態克隆異常,在不知道異常類型情況下複製異常。
• ice_throw 在不知道某個異常的確切運行時類型的情況下拋出它。
• ice_print  打印異常的名字,或直接使用重載的<<操作符:
 

try {
    // ...
} catch (const Ice::Exception & e) {
    cerr << e << endl;
}

出於效率上的考慮,總是通過const引用捕捉異常。這樣,編譯器就能夠生成不調用異常複製構造器的代碼(當然,同時也防止異常被切成基類型)。調用操作拋出異常時,該操作的out參數是否賦值無法確定,但是操作的返回值肯定沒有返回。

一條異常路徑:

• Ice::ConnectTimeoutException

• Ice::TimeoutException

• Ice::LocalException

• Ice::UserException

• Ice::Exception
很少需要以最深派生類型捕獲運行時異常,而是以LocalException捕獲它們;對細粒度異常處理感興趣的,主要是Ice運行時實現。

4、接口映射 
module M {
    interface Simple {
        void op();
    };
};
客戶端,接口映射到類:
          ↓
namespace IceProxy {
    namespace M {
        class Simple;
    }
}
namespace M{
    class Simple; — 代理類
    typedef IceInternal::ProxyHandle< ::IceProxy::M::Simple> SimplePrx; — 代理句柄
    typedef IceInternal::Handle< ::M::Simple> SimplePtr;
}
namespace IceProxy {
    namespace M {
        class Simple : public virtual IceProxy::Ice::Object {
        public:
            typedef ::M::SimplePrx ProxyType;
            typedef ::M::SimplePtr PointerType;
            void op();
            void op(const Ice::Context&);
            //....
        };
    };
}
IceProxy::M::Simple是服務器Simple接口的客戶端代理類,它繼承自IceProxy::Ice::Object。接口中的每個操作,代理類都有兩個重載的、同名的成員函數。其中一個函數的最後一個參數的類型是Ice::Context——Ice上下文,dictionary<string, string>結構,客戶端向服務器發送請求時,將該結構一起發送。

客戶端不能直接實例化代理類:
IceProxy::M::Simple s;  ← 錯誤
客戶端只能使用代理句柄SimplePrx訪問代理類Simple。代理句柄能夠自動管理內存,支持賦值和比較操作符:
SimplePrx prx1 = ...;
SimplePrx prx2(prx1);
prx1=prx2;
assert(prx1==prx2);
cout << prx1 << ';' << prx2 << endl; ← 等效方法 prx->ice_toString()
類似方法:communicator->proxyToString(prx);

BasePrx base = ...; 
DerivedPrx derived = DerivedPrx::checkedCast(base); ← 檢查轉換:遠程訪問,失敗時返回null。
derived = DerivedPrx::uncheckedCast(base); ← 不檢查的轉換:不進行遠程訪問,失敗時行爲不確定。

代理方法:
Ice::ObjectPrx base = communicator->stringToProxy(...);
HelloPrx hello = HelloPrx::checkedCast(base);
hello = hello->ice_timeout(10000); 
hello->sayHello();

代理比較:
代理同一性比較:==,!=,<,<=,>,>=比較,布爾比較;
代理的對象同一性比較:
bool proxyIdentityLess(p1,p2);
bool proxyIdentityEqual(p1,p2);
bool proxyIdentityAndFacetLess(p1,p2);
bool proxyIdentityAndFacetEqual(p1,p2);

5、操作映射 
對於所有被映射的Slice 類型而言都一樣:你可以安全地忽略操作的返回值,不管它的類型是什麼——返回值總是通過傳值返回。如果你忽略返回值,不會發生內存泄漏,因爲返回值的析構器會按照需要釋放內存。

in 參數,使用傳值或const引用傳遞;
out參數,使用引用傳遞。

支持鏈式調用:
p2->setName(p1->getName()); ← p1,p2爲代理

6、異常處理 
SimplePrx p = ...; 
try {
    p->op();
} catch (const SimpleError & t) {
    cout << "Simple Error: " << t.reason << endl;
}
應該總是使用const引用捕捉異常。這樣,編譯器就能生成不調用異常複製構造器的代碼,同時防止異常切成基類型。操作拋出異常後,操作的參數是否已改變不能確定;但是接收操作返回值的變量沒有被改寫。

7、類映射: 
Slice類映射到同名C++類。
• 每個成員映射爲C++類public成員;
• 每個操作映射爲虛成員函數;
• 類繼承自Ice::Object(代理類繼承自Ice::ObjectPrx);
• 兩個構造器,一個缺省,一個帶有所有成員參數;
• 生成<class-name>Ptr智能指針(<class-name>Prx是代理句柄)。

類繼承自Ice::Object基類的成員函數:
• ice_isA:是否支持指定類型ID
• ice_ping:類可達測試
• ice_ids:對象支持的類序列,從根類到最深派生類
• ice_id:類的實際ID
• ice_staticId:類的靜態類型ID
• ice_hash:類的哈希值
• ice_clone:多態淺複製
• ice_preMarshal:整編本類前調用
• ice_postUnmarshal:解編本類後調用
• ice_dispatch:請求分派給服務者
• 比較操作符:== != < <= > >=

類成員可見性:
修改類成員的可見性,使用元數據指令:["protected"]

類的構造函數:
類的缺省構造函數,構造每個數據成員,簡單內置類型不初始化,複雜類型使用該類型自己的缺省構造初始化。
類的非缺省構造函數,每個數據成員一個參數,可以用一條語句構造和初始化。所有參數按照基類到派生類的順序,加入參數序列。

類的操作:
類的操作被映射爲純虛成員函數,必須創建派生類,實現這些操作,才能使用類。

類工廠:
有操作的類必須提供類工廠,無操作的類不必提供類工廠。
⑴實現類工廠
class SimpleFactory : public Ice::ObjectFactory {
public:
    virtual Ice::ObjectPtr create(const std::string &) {
        assert(type == M::Simple::ice_staticId());
        return new SimpleI;
    }
    virtual void destroy() {}
};
⑵註冊類工廠:
Ice::CommunicatorPtr ic = ...;
ic->addObjectFactory(new SimpleFactory, M::Simple::ice_staticId());
⑶使用類工廠:
現在,每當Ice實例化M::Simple類時,就會自動調用SimpleFactory的create方法,創建SimpleI類,客戶端可以使用該類的op方法。

類的智能指針:
Slice 編譯器會爲每種類類型生成智能指針。對於Slice類<class-name>,編譯器會生成叫作<class-name>Ptr 的C++ 智能指針:
    TimeOfDayPtr tod = new TimeOfDayI;
不能在棧上分配類實例,也不能用靜態變量定義類實例。類必須由new分配。

智能指針是異常安全的,當拋出異常時,智能指針能夠安全地析構。但要注意:在構造器中拋出異常,可能使得智能指針不安全;循環引用的情況下,智能指針也會不安全,這種情況下,可以使用Ice::collectGarbage();  收集因循環引用沒有釋放的對象。當然只有在循環引用的情況下,垃圾收集器纔有用。在沒有循環引用的情況下,使用垃圾收集器沒有意義。把Ice.GC.Interval 設成5,收集器線程就會每5秒運行一次垃圾收集器。

智能指針的比較只會比較內存地址,即比較兩個指針是否指向同一物理類實例。

 

轉自:http://blog.csdn.net/colorado

發佈了148 篇原創文章 · 獲贊 42 · 訪問量 195萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章