A Boost/Serialization demo for C++ classes implemented from several compilation units (shared libraries):
- Author: F.Mauger
- Affiliation: Université de Caen Normandie, LPC Caen (CNRS/IN2P3)
- Copyright : Creative Commons BY-NC-SA (this README file and C++ code)
- Date: 2016-05-25
- Update: 2017-05-02
- Keywords: Boost,Serialization,Compilation units
This demo has been created as a test bench of some advanced usage of the Boost Serialization Library on some systems of interest (mostly computers running modern Linux used for computing, simulation and data analysis for experimental physics). It is provided as is, first for my personal usage and experimentation but also in the hope it could help someone else to understand and setup Boost based serialization features in his/her own code.
This set of sample C++ files illustrates how to implement serialization functionalities, through the Boost/Serialization library, in several (simple) toy classes defined from three shared libraries with dependency relationship. The libraries instantiate dedicated templatized code for the serialization of the provided classes (Boost XML/txt archives), as well as registration (export) mechanism for polymorphic classes (see the Boost/Serialization documentation for details).
Several use cases are considered:
- Plain serialization of simple classes:
Simple class xy::Y
with an attribute of the
class xy::X
in the first library (libXY
). Class z::Z
in
the second library (libZ
) with a class xy::X
attribute
and a class xy::Y
attribute from the first
library (libXY
).
+-----------------+
| xy::X |
+-----------------+
| val : uint32_t |
+-----------------+
+-----------------+
| xy::Y |
+-----------------+
| x : xy::X |
+-----------------+
First shared lib (libXY)
--------------------------------------------
Second shared lib (libZ)
+-----------------+
| z::Z |
+-----------------+
| y : xy::Y |
| x : xy::X |
+-----------------+
-
Serialization of polymorphic classes through pointer to a base class:
Class
xy::B
inherited from polymorphic classxy::A
in the first library (libXY
); classz::C
in the second library (libZ
) inherited from classxy::B
from the first library, classplugin::P
in the third library (libPlugin
) inherited from classxy::A
from the first library.
+-----------------+
| /xy::A/ |
+-----------------+
| val : uint32_t |
+-----------------+
| /to_string/ |
+-----------------+
^ ^
inheritance | |
| +--------------------------------+
| |
+-----------------+ |
| /xy::B/ | |
+-----------------+ |
| val2 : uint32_t | |
+-----------------+ |
| /to_string/ | |
+-----------------+ |
^ |
| First shared lib (libXY) |
--------|----------------------------------- |
| Second shared lib (libZ) |
inheritance | |
+-----------------+ |
| /z::C/ | |
+-----------------+ |
| val3 : uint32_t | |
+-----------------+ |
| /to_string/ | |
+-----------------+ |
|
+--------------------------------------+
--------|-----------------------------------
| Third shared lib (libPlugin)
inheritance |
+-----------------+
| plugin::P |
+-----------------+
| val2 : uint32_t |
+-----------------+
- Serialization of polymorphic objects only known from a plugin library, dynamically loaded at runtime from a compilation unit (executable) that does not know about the class(es) of the serialized objects.
Various test programs are provided to test (de)serialization of the classes. We use the official XML Boost archive format. Optionally the use of EOS portable binary archives (version 5.1) can be activated.
The libXY.so
(namespace xy
) shared library contains the
definitions of serializable classes xy::X
, xy::Y
, xy::A
and xy::B
as well as instantiated serialization code and
registration code (for class xy::B
) with regards of Boost XML and
text archives.
- Class
xy::X
:X.hpp
,X.cpp
,X-serial.hpp
(implementation of the templatized serialization method). - Class
xy::Y
with an attribute of typexy::X
:Y.hpp
,Y.cpp
,Y-serial.hpp
(implementation of the templatized serialization method). - Class
xy::A
(polymorphic class) :A.hpp
,A.cpp
,A-serial.hpp
(implementation of the templatized serialization method). - Class
xy::B
(inherited fromxy::A
) :B.hpp
(with export key),B.cpp
,B-serial.hpp
(implementation of the templatized serialization method). - Instantiation of serialization code for classes
xy::X
,xy::Y
,xy::A
,xy::B
and classxy::B
registration (export):serial_xy_ab.cpp
. - Abstract class
xy::BasePlugin
: base class for object factory classes. Objects instantiated from such factories must inherit thexy::A
class. - Class
xy::plugin_deck
: provide a singleton which points to an object factory instance. Objects instantiated from such factories inherit thexy::A
class.
XY/testing/test_X.cxx
: serialization of classxy::X
.XY/testing/test_Y.cxx
: serialization of classxy::Y
.XY/testing/test_AB.cxx
: serialization of pointers to objects (xy::A
orxy::B
) inherited from polymorphic classxy::A
.
The libZ.so
(namespace z
) shared library contains the
definitions of serializable classes z::Z
and z::C
as well as
instantiated serialization code and registration code (for class
z::C
) with regards of Boost XML and text archives.
The libZ.so
DLL is explicitely linked to the libXY.so
DLL.
- Class
z::Z
with an attribute of typexy::Y
and an attribute of typexy::X
:Z.hpp
,Z.cpp
,Z-serial.hpp
. - Class
z::C
(inherited fromxy::B
) :C.hpp
(with export key),C.cpp
,C-serial.hpp
. - Instantiation of serialization code for classes
z::Z
,z::C
, and classz::C
registration (export):serial_z_c.cpp
.
Z/testing/test_Z.cxx
: serialization of classz::Z
.Z/testing/test_C.cxx
: serialization of pointers to objects (xy::A
,xy::B
orz::C
) inherited from polymorphic classxy::A
.
The libPlugin.so
(namespace plugin
) shared library contains the
definitions of serializable class plugin::P
as well as
instantiated serialization and registration code (for class
plugin::P
) with regards of Boost XML and text archives.
The libPlugin.so
DLL is explicitely linked to the libZ.so
DLL.
At loading, the libPlugin.so
DLL instantiates a specific object factory and register it
in the libXY.so
DLL. From this factory, it is then possible to randomly instantiate objects
of various types (xy::A
, xy::B
,z::C
or plugin::P
) from a
compilation unit which is only linked to the libXY.so
DLL and from which the libPlugin.so
DLL has been dynamically loaded.
- Class
plugin::P
(inherited fromxy::A
) :P.hpp
(with export key),P.cpp
,P-serial.hpp
. - Instantiation of serialization code for classes
plugin::P
and class registration (export):serial_plugin_p.cpp
. - Class
plugin::Plugin
: object factory class. Objects of typesxy::A
,xy::B
,z::C
orplugin::P
are randomly instantiated from this factory. - Class
plugin::init_lib
: provide a singleton for initialization of the library at loading. Aplugin::Plugin
instance is automatically registered in thexy:plugin_deck
singleton in thelibXY.so
DLL.
Plugin/testing/test_Plugin.cxx
: use a factory for random instantiation of severalxy::A
,xy::B
,z::C
orplugin::P
objects and serialization through a vector of shared pointers. The executable is explicitely linked to thelibPlugin.so
DLL and thus thelibZ.so
andlibXY.so
DLLs..Plugin/testing/test_Plugin_2.cxx
: use a factory for random instantiation ofxy::A
,xy::B
,z::C
andplugin::P
objects and serialization through a vector of shared pointers. The executable is only explicitely linked to thelibXY.so
DLL. ThelibPlugin.so
DLL is loaded dynamically by the executable at runtime which makes possible the serialization of random objects of typez::C
andplugin::P
thanks to export code implemented in bothlibZ.so
andlibPlugin.so
DLLs.
This demo has been tested under Linux but should work on any other OS with a descent C++ compiler and Boost/Serialization installed on the system.
A CMake script is provided to build the full chain of software on Linux (DLLs and test executable).
These examples have been successfully tested on Linux Ubuntu 16.04 with :
* gcc 5.4.0
* Boost/Serialization library versions 1.58 (system installation on ``/usr``) and 1.60.
* CMake 3.5.1
The demo uses CMake (>= 3.3) as its build system.
The demo supports two optional parameters:
-
BOOST_ROOT
: The path where the Boost libraries are installed. For a system installation on Linux, this should be/usr
and automatically found by CMake.Example: to target a specific Boost installation:
$ cmake ... -DBOOST_ROOT=/opt/sw/Boost/install-1.60 ...
-
BSTCUD_WITH_EOS
: This flag enables support and test of the EOS Portable Binary Archives (version 5.1, by Christian Pfligersdorffer). By default it is inhibited.Example:
$ cmake ... -DBSTCUD_WITH_EOS=ON ...
- from the source directory, you should first create a build directory and cd in it:
$ mkdir _build.d
$ cd _build.d
- then configure and build the demo:
$ cmake [-DBOOST_ROOT=/path/to/boost/installation] [-DBSTCUD_WITH_EOS=ON] ..
$ make
$ ls XY/ Z/ Plugin/
By default, the CMake find_package(Boost ...)
function will search for
a system installation of the Boost library
from the /usr
directory. This can be changed with the -DBOOST_ROOT=...
variable.
- finally run the test programs:
$ make test