列集(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>(或者同时包含两者),对于其他的STL和Boost库也是一样。
#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;
// }
当处理指向多态对象指针和循环指针的时候,序列化会变成一个很复杂的事情。SF
和Boost.Serialization
都能处理这些情况,但是用的是不同的方法,所以为了适应两种序列化系统需要写不同的序列化代码。下面的例子使用了SF
和Boost.Serialization
来发送多态对象。
{
// 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 & base , const 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_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 &e = clientF;
e.func5();
}