540 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			540 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | // Copyright (C) 2006 Douglas Gregor <doug.gregor -at- gmail.com> | ||
|  | 
 | ||
|  | // Use, modification and distribution is subject to the Boost Software | ||
|  | // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||
|  | // http://www.boost.org/LICENSE_1_0.txt) | ||
|  | 
 | ||
|  | //  Authors: Douglas Gregor | ||
|  | 
 | ||
|  | /** @file serialize.hpp | ||
|  |  * | ||
|  |  *  This file provides Boost.Serialization support for Python objects | ||
|  |  *  within Boost.MPI. Python objects can be serialized in one of two | ||
|  |  *  ways. The default serialization method involves using the Python | ||
|  |  *  "pickle" module to pickle the Python objects, transmits the | ||
|  |  *  pickled representation, and unpickles the result when | ||
|  |  *  received. For C++ types that have been exposed to Python and | ||
|  |  *  registered with register_serialized(), objects are directly | ||
|  |  *  serialized for transmissing, skipping the pickling step. | ||
|  |  */ | ||
|  | #ifndef BOOST_MPI_PYTHON_SERIALIZE_HPP | ||
|  | #define BOOST_MPI_PYTHON_SERIALIZE_HPP | ||
|  | 
 | ||
|  | #include <boost/mpi/python/config.hpp> | ||
|  | 
 | ||
|  | #include <boost/python/object.hpp> | ||
|  | #include <boost/python/str.hpp> | ||
|  | #include <boost/python/extract.hpp> | ||
|  | 
 | ||
|  | #include <memory> | ||
|  | #include <map> | ||
|  | 
 | ||
|  | #include <boost/function/function3.hpp> | ||
|  | 
 | ||
|  | #include <boost/mpl/bool.hpp> | ||
|  | #include <boost/mpl/if.hpp> | ||
|  | 
 | ||
|  | #include <boost/serialization/split_free.hpp> | ||
|  | #include <boost/serialization/array.hpp> | ||
|  | 
 | ||
|  | #include <boost/assert.hpp> | ||
|  | 
 | ||
|  | #include <boost/type_traits/is_fundamental.hpp> | ||
|  | 
 | ||
|  | #define BOOST_MPI_PYTHON_FORWARD_ONLY | ||
|  | #include <boost/mpi/python.hpp> | ||
|  | 
 | ||
|  | /************************************************************************ | ||
|  |  * Boost.Python Serialization Section                                   * | ||
|  |  ************************************************************************/ | ||
|  | #if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE) | ||
|  | /** | ||
|  |  * @brief Declare IArchive and OArchive as a Boost.Serialization | ||
|  |  * archives that can be used for Python objects. | ||
|  |  * | ||
|  |  * This macro can only be expanded from the global namespace. It only | ||
|  |  * requires that Archiver be forward-declared. IArchiver and OArchiver | ||
|  |  * will only support Serialization of Python objects by pickling | ||
|  |  * them. If the Archiver type should also support "direct" | ||
|  |  * serialization (for C++ types), use | ||
|  |  * BOOST_PYTHON_DIRECT_SERIALIZATION_ARCHIVE instead. | ||
|  |  */ | ||
|  | #  define BOOST_PYTHON_SERIALIZATION_ARCHIVE(IArchiver, OArchiver)        \ | ||
|  | namespace boost { namespace python { namespace api {    \ | ||
|  |   template<typename R, typename T>                      \ | ||
|  |   struct enable_binary< IArchiver , R, T> {};           \ | ||
|  |                                                         \ | ||
|  |   template<typename R, typename T>                      \ | ||
|  |   struct enable_binary< OArchiver , R, T> {};           \ | ||
|  | } } }  | ||
|  | # else | ||
|  | #  define BOOST_PYTHON_SERIALIZATION_ARCHIVE(IArchiver, OArchiver) | ||
|  | #endif | ||
|  | 
 | ||
|  | /** | ||
|  |  * @brief Declare IArchiver and OArchiver as a Boost.Serialization | ||
|  |  * archives that can be used for Python objects and C++ objects | ||
|  |  * wrapped in Python. | ||
|  |  * | ||
|  |  * This macro can only be expanded from the global namespace. It only | ||
|  |  * requires that IArchiver and OArchiver be forward-declared. However, | ||
|  |  * note that you will also need to write | ||
|  |  * BOOST_PYTHON_DIRECT_SERIALIZATION_ARCHIVE_IMPL(IArchiver, | ||
|  |  * OArchiver) in one of your translation units. | ||
|  | 
 | ||
|  | DPG PICK UP HERE | ||
|  |  */ | ||
|  | #define BOOST_PYTHON_DIRECT_SERIALIZATION_ARCHIVE(IArchiver, OArchiver) \ | ||
|  | BOOST_PYTHON_SERIALIZATION_ARCHIVE(IArchiver, OArchiver)                \ | ||
|  | namespace boost { namespace python { namespace detail {                 \ | ||
|  | template<>                                                              \ | ||
|  | BOOST_MPI_PYTHON_DECL direct_serialization_table< IArchiver , OArchiver >& \ | ||
|  |  get_direct_serialization_table< IArchiver , OArchiver >();             \ | ||
|  | }                                                                       \ | ||
|  |                                                                         \ | ||
|  | template<>                                                              \ | ||
|  | struct has_direct_serialization< IArchiver , OArchiver> : mpl::true_ { }; \ | ||
|  |                                                                         \ | ||
|  | template<>                                                              \ | ||
|  | struct output_archiver< IArchiver > { typedef OArchiver type; };        \ | ||
|  |                                                                         \ | ||
|  | template<>                                                              \ | ||
|  | struct input_archiver< OArchiver > { typedef IArchiver type; };         \ | ||
|  | } } | ||
|  | 
 | ||
|  | /** | ||
|  |  * @brief Define the implementation for Boost.Serialization archivers | ||
|  |  * that can be used for Python objects and C++ objects wrapped in | ||
|  |  * Python. | ||
|  |  * | ||
|  |  * This macro can only be expanded from the global namespace. It only | ||
|  |  * requires that IArchiver and OArchiver be forward-declared. Before | ||
|  |  * using this macro, you will need to declare IArchiver and OArchiver | ||
|  |  * as direct serialization archives with | ||
|  |  * BOOST_PYTHON_DIRECT_SERIALIZATION_ARCHIVE(IArchiver, OArchiver). | ||
|  |  */ | ||
|  | #define BOOST_PYTHON_DIRECT_SERIALIZATION_ARCHIVE_IMPL(IArchiver, OArchiver) \ | ||
|  | namespace boost { namespace python { namespace detail {                 \ | ||
|  | template                                                                \ | ||
|  |   class BOOST_MPI_PYTHON_DECL direct_serialization_table< IArchiver , OArchiver >; \ | ||
|  |                                                                         \ | ||
|  | template<>                                                              \ | ||
|  |  BOOST_MPI_PYTHON_DECL                                                  \ | ||
|  |  direct_serialization_table< IArchiver , OArchiver >&                   \ | ||
|  |  get_direct_serialization_table< IArchiver , OArchiver >( )             \ | ||
|  | {                                                                       \ | ||
|  |   static direct_serialization_table< IArchiver, OArchiver > table;      \ | ||
|  |   return table;                                                         \ | ||
|  | }                                                                       \ | ||
|  | } } } | ||
|  | 
 | ||
|  | namespace boost { namespace python { | ||
|  | 
 | ||
|  | /** | ||
|  |  * INTERNAL ONLY | ||
|  |  * | ||
|  |  * Provides access to the Python "pickle" module from within C++. | ||
|  |  */ | ||
|  | class BOOST_MPI_PYTHON_DECL pickle { | ||
|  |   struct data_t; | ||
|  | 
 | ||
|  | public: | ||
|  |   static str dumps(object obj, int protocol = -1); | ||
|  |   static object loads(str s); | ||
|  |    | ||
|  | private: | ||
|  |   static void initialize_data(); | ||
|  | 
 | ||
|  |   static data_t* data; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * @brief Whether the input/output archiver pair has "direct" | ||
|  |  * serialization for C++ objects exposed in Python. | ||
|  |  * | ||
|  |  * Users do not typically need to specialize this trait, as it will be | ||
|  |  * specialized as part of the macro | ||
|  |  * BOOST_PYTHON_DIRECT_SERIALIZATION_ARCHIVE. | ||
|  |  */ | ||
|  | template<typename IArchiver, typename OArchiver> | ||
|  | struct has_direct_serialization : mpl::false_ { }; | ||
|  | 
 | ||
|  | /** | ||
|  |  *  @brief A metafunction that determines the output archiver for the | ||
|  |  *  given input archiver. | ||
|  |  * | ||
|  |  * Users do not typically need to specialize this trait, as it will be | ||
|  |  * specialized as part of the macro | ||
|  |  * BOOST_PYTHON_DIRECT_SERIALIZATION_ARCHIVE. | ||
|  |  */ | ||
|  | template<typename IArchiver> struct output_archiver { }; | ||
|  | 
 | ||
|  | /** | ||
|  |  *  @brief A metafunction that determines the input archiver for the | ||
|  |  *  given output archiver. | ||
|  |  * | ||
|  |  * Users do not typically need to specialize this trait, as it will be | ||
|  |  * specialized as part of the macro | ||
|  |  * BOOST_PYTHON_DIRECT_SERIALIZATION_ARCHIVE. | ||
|  |  * | ||
|  |  */ | ||
|  | template<typename OArchiver> struct input_archiver { }; | ||
|  | 
 | ||
|  | namespace detail { | ||
|  | 
 | ||
|  |   /** | ||
|  |    * INTERNAL ONLY | ||
|  |    * | ||
|  |    * This class contains the direct-serialization code for the given | ||
|  |    * IArchiver/OArchiver pair. It is intended to be used as a | ||
|  |    * singleton class, and will be accessed when (de-)serializing a | ||
|  |    * Boost.Python object with an archiver that supports direct | ||
|  |    * serializations. Do not create instances of this class directly: | ||
|  |    * instead, use get_direct_serialization_table. | ||
|  |    */ | ||
|  |   template<typename IArchiver, typename OArchiver> | ||
|  |   class BOOST_MPI_PYTHON_DECL direct_serialization_table | ||
|  |   { | ||
|  |   public: | ||
|  |     typedef boost::function3<void, OArchiver&, const object&, const unsigned int> | ||
|  |       saver_t; | ||
|  |     typedef boost::function3<void, IArchiver&, object&, const unsigned int> | ||
|  |       loader_t; | ||
|  | 
 | ||
|  |     typedef std::map<PyTypeObject*, std::pair<int, saver_t> > savers_t; | ||
|  |     typedef std::map<int, loader_t> loaders_t; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Retrieve the saver (serializer) associated with the Python | ||
|  |      * object @p obj. | ||
|  |      * | ||
|  |      *   @param obj The object we want to save. Only its (Python) type | ||
|  |      *   is important. | ||
|  |      * | ||
|  |      *   @param descriptor The value of the descriptor associated to | ||
|  |      *   the returned saver. Will be set to zero if no saver was found | ||
|  |      *   for @p obj. | ||
|  |      * | ||
|  |      *   @returns a function object that can be used to serialize this | ||
|  |      *   object (and other objects of the same type), if possible. If | ||
|  |      *   no saver can be found, returns an empty function object.. | ||
|  |      */ | ||
|  |     saver_t saver(const object& obj, int& descriptor) | ||
|  |     { | ||
|  |       typename savers_t::iterator pos = savers.find(obj.ptr()->ob_type); | ||
|  |       if (pos != savers.end()) { | ||
|  |         descriptor = pos->second.first; | ||
|  |         return pos->second.second; | ||
|  |       } | ||
|  |       else { | ||
|  |         descriptor = 0; | ||
|  |         return saver_t(); | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Retrieve the loader (deserializer) associated with the given | ||
|  |      * descriptor. | ||
|  |      * | ||
|  |      *  @param descriptor The descriptor number provided by saver() | ||
|  |      *  when determining the saver for this type. | ||
|  |      * | ||
|  |      *  @returns a function object that can be used to deserialize an | ||
|  |      *  object whose type is the same as that corresponding to the | ||
|  |      *  descriptor. If the descriptor is unknown, the return value | ||
|  |      *  will be an empty function object. | ||
|  |      */ | ||
|  |     loader_t loader(int descriptor) | ||
|  |     { | ||
|  |       typename loaders_t::iterator pos = loaders.find(descriptor); | ||
|  |       if (pos != loaders.end()) | ||
|  |         return pos->second; | ||
|  |       else | ||
|  |         return loader_t(); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Register the type T for direct serialization. | ||
|  |      * | ||
|  |      *  @param value A sample value of the type @c T. This may be used | ||
|  |      *  to compute the Python type associated with the C++ type @c T. | ||
|  |      * | ||
|  |      *  @param type The Python type associated with the C++ type @c | ||
|  |      *  T. If not provided, it will be computed from the same value @p | ||
|  |      *  value. | ||
|  |      */ | ||
|  |     template<typename T> | ||
|  |     void register_type(const T& value = T(), PyTypeObject* type = 0) | ||
|  |     { | ||
|  |       // If the user did not provide us with a Python type, figure it | ||
|  |       // out for ourselves. | ||
|  |       if (!type) { | ||
|  |         object obj(value); | ||
|  |         type = obj.ptr()->ob_type; | ||
|  |       } | ||
|  | 
 | ||
|  |       register_type(default_saver<T>(), default_loader<T>(type), value, type); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Register the type T for direct serialization. | ||
|  |      * | ||
|  |      *  @param saver A function object that will serialize a | ||
|  |      *  Boost.Python object (that represents a C++ object of type @c | ||
|  |      *  T) to an @c OArchive. | ||
|  |      * | ||
|  |      *  @param loader A function object that will deserialize from an | ||
|  |      *  @c IArchive into a Boost.Python object that represents a C++ | ||
|  |      *  object of type @c T. | ||
|  |      * | ||
|  |      *  @param value A sample value of the type @c T. This may be used | ||
|  |      *  to compute the Python type associated with the C++ type @c T. | ||
|  |      * | ||
|  |      *  @param type The Python type associated with the C++ type @c | ||
|  |      *  T. If not provided, it will be computed from the same value @p | ||
|  |      *  value. | ||
|  |      */ | ||
|  |     template<typename T> | ||
|  |     void register_type(const saver_t& saver, const loader_t& loader,  | ||
|  |                        const T& value = T(), PyTypeObject* type = 0) | ||
|  |     { | ||
|  |       // If the user did not provide us with a Python type, figure it | ||
|  |       // out for ourselves. | ||
|  |       if (!type) { | ||
|  |         object obj(value); | ||
|  |         type = obj.ptr()->ob_type; | ||
|  |       } | ||
|  | 
 | ||
|  |       int descriptor = savers.size() + 1; | ||
|  |       if (savers.find(type) != savers.end()) | ||
|  |         return; | ||
|  | 
 | ||
|  |       savers[type] = std::make_pair(descriptor, saver); | ||
|  |       loaders[descriptor] = loader; | ||
|  |     } | ||
|  | 
 | ||
|  |   protected: | ||
|  |     template<typename T> | ||
|  |     struct default_saver { | ||
|  |       void operator()(OArchiver& ar, const object& obj, const unsigned int) { | ||
|  |         T value = extract<T>(obj)(); | ||
|  |         ar << value; | ||
|  |       } | ||
|  |     }; | ||
|  | 
 | ||
|  |     template<typename T> | ||
|  |     struct default_loader { | ||
|  |       default_loader(PyTypeObject* type) : type(type) { } | ||
|  | 
 | ||
|  |       void operator()(IArchiver& ar, object& obj, const unsigned int) { | ||
|  |         // If we can, extract the object in place. | ||
|  |         if (!is_fundamental<T>::value && obj && obj.ptr()->ob_type == type) { | ||
|  |           ar >> extract<T&>(obj)(); | ||
|  |         } else { | ||
|  |           T value; | ||
|  |           ar >> value; | ||
|  |           obj = object(value); | ||
|  |         } | ||
|  |       } | ||
|  | 
 | ||
|  |     private: | ||
|  |       PyTypeObject* type; | ||
|  |     }; | ||
|  | 
 | ||
|  |     savers_t savers; | ||
|  |     loaders_t loaders; | ||
|  |   }; | ||
|  | 
 | ||
|  |   /** | ||
|  |    * @brief Retrieve the direct-serialization table for an | ||
|  |    * IArchiver/OArchiver pair. | ||
|  |    * | ||
|  |    * This function is responsible for returning a reference to the | ||
|  |    * singleton direct-serialization table. Its primary template is | ||
|  |    * left undefined, to force the use of an explicit specialization | ||
|  |    * with a definition in a single translation unit. Use the macro | ||
|  |    * BOOST_PYTHON_DIRECT_SERIALIZATION_ARCHIVE_IMPL to define this | ||
|  |    * explicit specialization. | ||
|  |    */ | ||
|  |   template<typename IArchiver, typename OArchiver> | ||
|  |   direct_serialization_table<IArchiver, OArchiver>& | ||
|  |   get_direct_serialization_table(); | ||
|  | } // end namespace detail  | ||
|  | 
 | ||
|  | /** | ||
|  |  * @brief Register the type T for direct serialization. | ||
|  |  * | ||
|  |  * The @c register_serialized function registers a C++ type for direct | ||
|  |  * serialization with the given @c IArchiver/@c OArchiver pair. Direct | ||
|  |  * serialization elides the use of the Python @c pickle package when | ||
|  |  * serializing Python objects that represent C++ values. Direct | ||
|  |  * serialization can be beneficial both to improve serialization | ||
|  |  * performance (Python pickling can be very inefficient) and to permit | ||
|  |  * serialization for Python-wrapped C++ objects that do not support | ||
|  |  * pickling. | ||
|  |  * | ||
|  |  *  @param value A sample value of the type @c T. This may be used | ||
|  |  *  to compute the Python type associated with the C++ type @c T. | ||
|  |  * | ||
|  |  *  @param type The Python type associated with the C++ type @c | ||
|  |  *  T. If not provided, it will be computed from the same value @p | ||
|  |  *  value. | ||
|  |  */ | ||
|  | template<typename IArchiver, typename OArchiver, typename T> | ||
|  | void | ||
|  | register_serialized(const T& value = T(), PyTypeObject* type = 0) | ||
|  | { | ||
|  |   detail::direct_serialization_table<IArchiver, OArchiver>& table =  | ||
|  |     detail::get_direct_serialization_table<IArchiver, OArchiver>(); | ||
|  |   table.register_type(value, type); | ||
|  | } | ||
|  | 
 | ||
|  | namespace detail { | ||
|  | 
 | ||
|  | /// Save a Python object by pickling it. | ||
|  | template<typename Archiver> | ||
|  | void  | ||
|  | save_impl(Archiver& ar, const boost::python::object& obj,  | ||
|  |           const unsigned int /*version*/, | ||
|  |           mpl::false_ /*has_direct_serialization*/) | ||
|  | { | ||
|  |   boost::python::str py_string = boost::python::pickle::dumps(obj); | ||
|  |   int len = boost::python::extract<int>(py_string.attr("__len__")()); | ||
|  |   const char* string = boost::python::extract<const char*>(py_string); | ||
|  |   ar << len << boost::serialization::make_array(string, len); | ||
|  | } | ||
|  | 
 | ||
|  | /// Try to save a Python object by directly serializing it; fall back | ||
|  | /// on pickling if required. | ||
|  | template<typename Archiver> | ||
|  | void  | ||
|  | save_impl(Archiver& ar, const boost::python::object& obj,  | ||
|  |           const unsigned int version, | ||
|  |           mpl::true_ /*has_direct_serialization*/) | ||
|  | { | ||
|  |   typedef Archiver OArchiver; | ||
|  |   typedef typename input_archiver<OArchiver>::type IArchiver; | ||
|  |   typedef typename direct_serialization_table<IArchiver, OArchiver>::saver_t | ||
|  |     saver_t; | ||
|  | 
 | ||
|  |   direct_serialization_table<IArchiver, OArchiver>& table =  | ||
|  |     get_direct_serialization_table<IArchiver, OArchiver>(); | ||
|  | 
 | ||
|  |   int descriptor = 0; | ||
|  |   if (saver_t saver = table.saver(obj, descriptor)) { | ||
|  |     ar << descriptor; | ||
|  |     saver(ar, obj, version); | ||
|  |   } else { | ||
|  |     // Pickle it | ||
|  |     ar << descriptor; | ||
|  |     detail::save_impl(ar, obj, version, mpl::false_()); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /// Load a Python object by unpickling it | ||
|  | template<typename Archiver> | ||
|  | void  | ||
|  | load_impl(Archiver& ar, boost::python::object& obj,  | ||
|  |           const unsigned int /*version*/,  | ||
|  |           mpl::false_ /*has_direct_serialization*/) | ||
|  | { | ||
|  |   int len; | ||
|  |   ar >> len; | ||
|  | 
 | ||
|  |   std::auto_ptr<char> string(new char[len]); | ||
|  |   ar >> boost::serialization::make_array(string.get(), len); | ||
|  |   boost::python::str py_string(string.get(), len); | ||
|  |   obj = boost::python::pickle::loads(py_string); | ||
|  | } | ||
|  | 
 | ||
|  | /// Try to load a Python object by directly deserializing it; fall back | ||
|  | /// on unpickling if required. | ||
|  | template<typename Archiver> | ||
|  | void  | ||
|  | load_impl(Archiver& ar, boost::python::object& obj,  | ||
|  |           const unsigned int version, | ||
|  |           mpl::true_ /*has_direct_serialization*/) | ||
|  | { | ||
|  |   typedef Archiver IArchiver; | ||
|  |   typedef typename output_archiver<IArchiver>::type OArchiver; | ||
|  |   typedef typename direct_serialization_table<IArchiver, OArchiver>::loader_t | ||
|  |     loader_t; | ||
|  | 
 | ||
|  |   direct_serialization_table<IArchiver, OArchiver>& table =  | ||
|  |     get_direct_serialization_table<IArchiver, OArchiver>(); | ||
|  | 
 | ||
|  |   int descriptor; | ||
|  |   ar >> descriptor; | ||
|  | 
 | ||
|  |   if (descriptor) { | ||
|  |     loader_t loader = table.loader(descriptor); | ||
|  |     BOOST_ASSERT(loader); | ||
|  | 
 | ||
|  |     loader(ar, obj, version); | ||
|  |   } else { | ||
|  |     // Unpickle it | ||
|  |     detail::load_impl(ar, obj, version, mpl::false_()); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | } // end namespace detail | ||
|  | 
 | ||
|  | template<typename Archiver> | ||
|  | void  | ||
|  | save(Archiver& ar, const boost::python::object& obj,  | ||
|  |      const unsigned int version) | ||
|  | { | ||
|  |   typedef Archiver OArchiver; | ||
|  |   typedef typename input_archiver<OArchiver>::type IArchiver; | ||
|  | 
 | ||
|  |   detail::save_impl(ar, obj, version,  | ||
|  |                     has_direct_serialization<IArchiver, OArchiver>()); | ||
|  | } | ||
|  | 
 | ||
|  | template<typename Archiver> | ||
|  | void  | ||
|  | load(Archiver& ar, boost::python::object& obj,  | ||
|  |      const unsigned int version) | ||
|  | { | ||
|  |   typedef Archiver IArchiver; | ||
|  |   typedef typename output_archiver<IArchiver>::type OArchiver; | ||
|  | 
 | ||
|  |   detail::load_impl(ar, obj, version,  | ||
|  |                     has_direct_serialization<IArchiver, OArchiver>()); | ||
|  | } | ||
|  | 
 | ||
|  | template<typename Archive> | ||
|  | inline void  | ||
|  | serialize(Archive& ar, boost::python::object& obj, const unsigned int version) | ||
|  | { | ||
|  |   boost::serialization::split_free(ar, obj, version); | ||
|  | } | ||
|  | 
 | ||
|  | } } // end namespace boost::python | ||
|  | 
 | ||
|  | /************************************************************************ | ||
|  |  * Boost.MPI-Specific Section                                           * | ||
|  |  ************************************************************************/ | ||
|  | namespace boost { namespace mpi { | ||
|  |  class packed_iarchive; | ||
|  |  class packed_oarchive; | ||
|  | } } // end namespace boost::mpi | ||
|  | 
 | ||
|  | BOOST_PYTHON_DIRECT_SERIALIZATION_ARCHIVE( | ||
|  |   ::boost::mpi::packed_iarchive, | ||
|  |   ::boost::mpi::packed_oarchive) | ||
|  | 
 | ||
|  | namespace boost { namespace mpi { namespace python { | ||
|  | 
 | ||
|  | template<typename T> | ||
|  | void | ||
|  | register_serialized(const T& value, PyTypeObject* type) | ||
|  | { | ||
|  |   using boost::python::register_serialized; | ||
|  |   register_serialized<packed_iarchive, packed_oarchive>(value, type); | ||
|  | } | ||
|  | 
 | ||
|  | } } } // end namespace boost::mpi::python | ||
|  | 
 | ||
|  | #endif // BOOST_MPI_PYTHON_SERIALIZE_HPP |