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
 |