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
							 |