分享

RCF—用于C++的进程间通讯(2)

 just_person 2012-03-29

列集(Marshaling

RCF决定哪个方向的参数被列集时,是遵循C++惯例的。特别地,一个接口的所有的参数都是入参(in parameter),所有的non-const引用参数都是in-out参数,所有的返回值都是出参(out parameter)。但是也没有强制规定一定要遵循这些in/out/inout惯例。

并不是C++里的所有东西都可以被安全地列集,这也限制了接口方法的参数类型。也就是说,指针和引用可以作为参数;指针的引用不允许作为参数;指针和引用不能作为返回值。

这也意味着如果一个接口的方法想要返回一个指针,比如一个多态指针,返回值就需要时一个像std::auto_ptr<> 或者 boost::shared_ptr<>的智能指针。或者其中一个参数可以是一个智能指针的non-const引用。

序列化

Echo那个例子只序列化了std::string对象,但它(RCF)在使用序列化的情况下几乎可以发送所有的C++类和结构。RCF拥有自己的序列化框架,名字就叫序列化框架(SF),同时它也支持Boost.Serialization框架,这个框架是Boost库的一部分。

一般说来,需要在将被序列化的类里面包含序列化代码。如果你在接口有一个std::vector<>参数,你需要包含<SF/vector.hpp>或者<boost/serialization/vector.hpp>(或者同时包含两者),对于其他的STLBoost库也是一样。

RCF接口中使用你自己的类,你需要一个自定义的序列化方法,在大多数情况下,这非常简单。
#include <boost/serialization/string.hpp>

#include 
<boost/serialization/map.hpp>
#include 
<boost/serialization/vector.hpp>

#include 
<SF/string.hpp>
#include 
<SF/map.hpp>
#include 
<SF/vector.hpp>

struct X
{
    
int myInteger;
    std::
string myString;
    std::map
<
        std::
string,
        std::map
<int,std::vector<int> > > myMap;
}
;

// this serialization function
// will work as is with both SF and B.S.

template
<typename Archive>
void serialize(Archive &ar, X &x)
{
    ar 
& x.myInteger & x.myString & x.myMap;
}


// if you need to distinguish between SF and B.S. serialization,
// specialize the SF serialization function:
//void serialize(SF::Archive &ar, X &x)
//{
//    ar & myInteger & myString & myMap;
//}

当处理指向多态对象指针和循环指针的时候,序列化会变成一个很复杂的事情。SFBoost.Serialization都能处理这些情况,但是用的是不同的方法,所以为了适应两种序列化系统需要写不同的序列化代码。下面的例子使用了SFBoost.Serialization来发送多态对象。

class Base
{
    
// some members here
    
// ...
}
;

typedef boost::shared_ptr
<Base> BasePtr;

class Derived1 : public Base
{
    
// some members here
    
// ...
}
;

class Derived2 : public Base
{
    
// some members here
    
// ...
}
;

template
<typename Archive>
void serialize(Archive &ar, Base &baseconst unsigned int)
{
    
// ...
}


template
<typename Archive>
void serialize(Archive &ar, Derived1 &derived1, const unsigned int)
{
    
// valid for both SF and B.S.
    serializeParent<Base>(derived1);

    
// ...
}


template
<typename Archive>
void serialize(Archive &ar, Derived2 &derived2, const unsigned int)
{
    
// valid for both SF and B.S.
    serializeParent<Base>(derived1);

    
// ...
}


// Boost type registration, needed on both server and client
BOOST_CLASS_EXPORT_GUID(Derived1, "Derived1")
BOOST_CLASS_EXPORT_GUID(Derived2, 
"Derived2")

RCF_BEGIN(I_PolymorphicArgTest, 
"")
    RCF_METHOD_R1(std::
string, typeOf, BasePtr)
RCF_END(I_PolymorphicArgTest)

class PolymorphicArgTest
{
public:
    std::
string typeOf(BasePtr basePtr)
    
{
        
return typeid(*basePtr).name();
    }

}
;

{
    
// SF type registration, needed on both server and client
    SF::registerType<Derived1>("Derived1");
    SF::registerType
<Derived2>("Derived2");

    RcfClient
<I_PolymorphicArgTest> client(endpoint);

    
// SF serialization (default)
    client.getClientStub().setSerializationProtocol(RCF::SfBinary);
    std::
string typeBase = client.typeOf( BasePtr(new Base()) );
    std::
string typeDerived1 = client.typeOf( BasePtr(new Derived1()) );
    std::
string typeDerived2 = client.typeOf( BasePtr(new Derived2()) );

    
// Boost serialization
    client.getClientStub().setSerializationProtocol(RCF::BsBinary);
    typeDerived2 
= client.typeOf( BasePtr(new Derived2()) );
}

继承(Inheritance

RCF接口现在支持多继承。不仅可以从别的接口继承,还可以继承自标准C++类。接口内的方法可以用它们的分派ID和它们所属的接口名来标识。这样的信息对于服务器端用来映射来自客户端的调用到正确的服务器端绑定来说已经足够了。下面的例子示范了接口继承:

RCF_BEGIN(I_A, "I_A")
    RCF_METHOD_V0(
void, func1)
RCF_END(I_Base)

RCF_BEGIN(I_B, 
"I_B")
    RCF_METHOD_V0(
void, func2)
RCF_END(I_Base)

// derives from I_A

RCF_BEGIN_INHERITED(I_C, 
"I_C", I_A)
    RCF_METHOD_V0(
void, func3)
RCF_END(I_Base)

// derives from I_A and I_B

RCF_BEGIN_INHERITED_2(I_D, 
"I_D", I_A, I_B)
    RCF_METHOD_V0(
void, func4)
RCF_END(I_Base)

class I_E
{
public:
    
virtual void func5() = 0;
}
;

// derives from abstract base class I_E

RCF_BEGIN_INHERITED(I_F, 
"I_F", I_E)
    RCF_METHOD_V0(
void, func5)
RCF_END(I_Base)

{
    RcfClient
<I_C> clientC(endpoint);
    clientC.func3();
    clientC.func1();

    RcfClient
<I_D> clientD(endpoint);
    clientD.func4();
    clientD.func2();
    clientD.func1();

    RcfClient
<I_F> clientF(endpoint);
    I_E 
&= clientF;
    e.func5();
}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多