## Third Party Serialization

RCF provides support for several third pary serialization frameworks.

### Boost.Serialization

Boost.Serialization is a library conceptually similar to RCF's internal serialization framework, providing generic serialization for C++ classes. For reference material and FAQ's on Boost.Serialization itself, please refer to Boost documentation and the Boost mailing lists.

To utilize Boost.Serialization within RCF, you will need to define `RCF_USE_BOOST_SERIALIZATION` when building RCF, and then provide Boost.Serialization `serialize()` functions for all your datatypes.

RCF supports two archive types from Boost.Serialization - binary archives and text archives. To specify which one you want to use, call `ClientStub::setSerializationProtocol()`:

    RcfClient<I_X> client( RCF::TcpEndpoint(50001) );

    // To use Boost.Serialization with binary archives.
    client.getClientStub().setSerializationProtocol(RCF::Sp_BsBinary);

    // To use Boost.Serialization with text archives.
    client.getClientStub().setSerializationProtocol(RCF::Sp_BsText);

If RCF has also been built with `RCF_USE_SF_SERIALIZATION` defined, you can also specify SF serialization:

    // To use SF serialization.
    client.getClientStub().setSerializationProtocol(RCF::Sp_SfBinary);

Given the choice between using SF and using Boost.Serialization, which should you use? The answer of course depends largely on the needs of your own application. However, within the context of RCF, we feel SF is a better choice for a number of reasons:

- SF is RCF's native serialization implementation. It is updated along with RCF, and tested against RCF. It's behavior and configuration are not dependent on any particular version of Boost.
- SF has a robust internal versioning scheme. The SF runtime can adjusts its archive formats to be compatible with any older version of SF. This capability is crucial for implementing backwards compatibility in distributed applications, and is lacking in Boost.Serialization.
- SF is optimized for IPC usage, where tens of thousands of archives may be created and destroyed every second.
- SF intentionally makes it easy to modify the types in your application, so that newer versions of an application can evolve their object models, without affecting wire compatibility with older versions of the same application (see Interchangeable types ). In contrast, Boost.Serialization requires exact matches on source and destination types.
- SF has a robust type registration system. Type registration with Boost.Serialization involves macros, global static objects, and implicit code generation, with application wide side-effects. In some versions of Boost, type registration even requires including headers in a particular order. In contrast, type registration with SF is as simple as calling `SF::registerType()` and `SF::registerBaseAndDerived()`.
- SF archives are binary and guaranteed to be portable across platforms. Boost.Serialization binary archives are not portable, and hence can't be used for cross-platform IPC. Boost.Serialization text archives are portable, but at the cost of being much slower than binary archives.
- SF serialization functions are not templated, which means their definitions can be moved to source files. Boost.Serialization serialization functions are generally templated on the archive type, thus requiring their implementations to be placed inline in header files, causing excessive coupling and longer compile times.
- Boost.Serialization archive formats can change implicitly, depending on global static code instantiations in unrelated parts of the same executable, to the point where the archives produced cannot be loaded again (see this bug report, which unfortunately was closed without a fix).

### Protocol Buffers

Protocol Buffers is an open source project released by Google, which uses a specialized language to define serialization schemas, from which actual serialization code is generated. The official Protocol Buffers compiler can generate code in three languages (C++, Java and Python), and various third party projects are available to provide support for other languages.

#### Protocol Buffer classes

RCF provides native marshaling support for classes generated by the Protocol Buffers compiler. To enable this support, define `RCF_USE_PROTOBUF` when building RCF. With `RCF_USE_PROTOBUF` defined, classes produced by the Protocol Buffers compiler, can be used directly in RCF interface declarations, and will be serialized and deserialized using the Protocol Buffer runtime.

For more information on building RCF with Protocol Buffer support, see Appendix - Building.

As an example, consider this .proto file.

    // Person.proto

    message Person {
      required int32 id = 1;
      required string name = 2;
      optional string email = 3;
    }

Running the Protocol Buffer compiler (in C++ mode) over `Person.proto` results in the two files `Person.pb.h` and `Person.pb.cc`, containing the implementation of the C++ class `Person`.

    // Person.pb.h

    class Person : public ::google::protobuf::Message {
    // ...
    }

To use the class `Person` in an RCF interface, simply include `Person.pb.h` . RCF will detect that the `Person` class is a Protocol Buffer class, and will use Protocol Buffer functions to serialize and deserialize `Person` instances.

    #include <RCF/../../test/protobuf/messages/cpp/Person.pb.h>

    RCF_BEGIN(I_X, "I_X")
        RCF_METHOD_R1(Person, echo, const Person &)
    RCF_END(I_X)

Protocol Buffer classes can be intermingled with native C++ classes, in RCF interfaces:

    RCF_BEGIN(I_X, "I_X")
        RCF_METHOD_R1(Person, echo, const Person &)
        RCF_METHOD_V4(void , func, int, const std::vector<std::string> &, Person &, RCF::ByteBuffer)
    RCF_END(I_X)

#### Protocol Buffer caching

The serialization and deserialization code generated by Protocol Buffers is highly optimized. However, to make the most of this performance, you may want to cache and reuse Protocol Buffer objects from call to call, rather than creating new ones. Protocol Buffer objects will hold on to any memory they allocate, and will reuse the memory in subsequent serialization and deserialization operations.

RCF provides server-side object caching, for this purpose. For example, to enable server-side caching of the `Person` class:

    RCF::ObjectPool & cache = RCF::getObjectPool();

    // Enable server-side caching for Person.
    // * Don't cache more than 10 Person objects.
    // * Call Person::Clear() before putting a Person object into the cache.
    cache.enableCaching<Person>(10, boost::bind(&Person::Clear, _1));