251 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
			
		
		
	
	
			251 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
| /**
 | |
|  * @file   boost_python_headers.hpp
 | |
|  * @author Paul Furgale <paul.furgale@gmail.com>
 | |
|  * @date   Mon Dec 12 10:36:03 2011
 | |
|  * 
 | |
|  * @brief  A header that specializes boost-python to work with fixed-sized Eigen types.
 | |
|  * 
 | |
|  * The original version of this library did not include these specializations and this caused
 | |
|  * assert failures when running on Ubuntu 10.04 32-bit. More information about fixed-size 
 | |
|  * vectorizable types in Eigen is available here: 
 | |
|  * http://eigen.tuxfamily.org/dox-devel/TopicFixedSizeVectorizable.html
 | |
|  *
 | |
|  * This code has been tested on Ubunutu 10.04 64 and 32 bit, OSX Snow Leopard and OSX Lion.
 | |
|  *
 | |
|  * This code is derived from boost/python/converter/arg_from_python.hpp
 | |
|  * Copyright David Abrahams 2002.
 | |
|  * Distributed under the Boost Software License, Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt)
 | |
|  * 
 | |
|  */
 | |
| #ifndef NUMPY_EIGEN_CONVERTERS_HPP
 | |
| #define NUMPY_EIGEN_CONVERTERS_HPP
 | |
| 
 | |
| #include <Eigen/Core>
 | |
| #include <boost/python.hpp>
 | |
| #include <boost/python/detail/referent_storage.hpp>
 | |
| #include <boost/python/converter/arg_from_python.hpp>
 | |
| #include <boost/python/converter/rvalue_from_python_data.hpp>
 | |
| #include <boost/python/tuple.hpp>
 | |
| 
 | |
| 
 | |
| namespace boost { namespace python { namespace detail {
 | |
|       template<typename T>
 | |
|       struct referent_size;
 | |
| 
 | |
|       // This bit of code makes sure we have 16 extra bytes to do the pointer alignment for fixed-sized Eigen types
 | |
|        template<typename T, int A, int B, int C, int D, int E>
 | |
|        struct referent_size< Eigen::Matrix<T,A,B,C,D,E>& >
 | |
|        {
 | |
|        	// Add 16 bytes so we can get alignment
 | |
|        	BOOST_STATIC_CONSTANT( std::size_t, value = sizeof(Eigen::Matrix<T,A,B,C,D,E>) + 16);
 | |
|        };
 | |
| 
 | |
|       // This bit of code makes sure we have 16 extra bytes to do the pointer alignment for fixed-sized Eigen types
 | |
|        template<typename T, int A, int B, int C, int D, int E>
 | |
|        struct referent_size< Eigen::Matrix<T,A,B,C,D,E> const & >
 | |
|        {
 | |
|        	// Add 16 bytes so we can get alignment
 | |
|        	BOOST_STATIC_CONSTANT( std::size_t, value = sizeof(Eigen::Matrix<T,A,B,C,D,E>) + 16);
 | |
|        };
 | |
| 
 | |
|       // This bit of code makes sure we have 16 extra bytes to do the pointer alignment for fixed-sized Eigen types
 | |
|        template<typename T, int A, int B, int C, int D, int E>
 | |
|        struct referent_size< Eigen::Matrix<T,A,B,C,D,E> >
 | |
|        {
 | |
|        	// Add 16 bytes so we can get alignment
 | |
|        	BOOST_STATIC_CONSTANT( std::size_t, value = sizeof(Eigen::Matrix<T,A,B,C,D,E>) + 16);
 | |
|        };
 | |
| 
 | |
| 
 | |
|     }}}
 | |
| 
 | |
| namespace boost { namespace python { namespace converter { 
 | |
| 
 | |
| 
 | |
|       template<typename S, int A, int B, int C, int D, int E>
 | |
|       struct rvalue_from_python_data< Eigen::Matrix<S,A,B,C,D,E> const &> : rvalue_from_python_storage< Eigen::Matrix<S,A,B,C,D,E> const & >
 | |
|       {
 | |
| 	typedef typename Eigen::Matrix<S,A,B,C,D,E> T;
 | |
| # if (!defined(__MWERKS__) || __MWERKS__ >= 0x3000)		 \
 | |
|   && (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 245)	 \
 | |
|   && (!defined(__DECCXX_VER) || __DECCXX_VER > 60590014)		\
 | |
|   && !defined(BOOST_PYTHON_SYNOPSIS) /* Synopsis' OpenCXX has trouble parsing this */
 | |
| 	// This must always be a POD struct with m_data its first member.
 | |
| 	BOOST_STATIC_ASSERT(BOOST_PYTHON_OFFSETOF(rvalue_from_python_storage<T>,stage1) == 0);
 | |
| # endif
 | |
| 
 | |
| 	// The usual constructor 
 | |
| 	rvalue_from_python_data(rvalue_from_python_stage1_data const & _stage1)
 | |
| 	{
 | |
| 	  this->stage1 = _stage1;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	// This constructor just sets m_convertible -- used by
 | |
| 	// implicitly_convertible<> to perform the final step of the
 | |
| 	// conversion, where the construct() function is already known.
 | |
| 	rvalue_from_python_data(void* convertible)
 | |
| 	{
 | |
| 	  this->stage1.convertible = convertible;
 | |
| 	}
 | |
| 	
 | |
| 	// Destroys any object constructed in the storage.
 | |
| 	~rvalue_from_python_data()
 | |
| 	{
 | |
| 	  // Realign the pointer and destroy
 | |
| 	  if (this->stage1.convertible == this->storage.bytes)
 | |
| 	    {
 | |
| 	      void * storage = reinterpret_cast<void *>(this->storage.bytes);
 | |
| 	      T * aligned = reinterpret_cast<T *>(reinterpret_cast<void *>((reinterpret_cast<size_t>(storage) & ~(size_t(15))) + 16));
 | |
| 	      
 | |
| 	      //std::cout << "Destroying " << (void*)aligned << std::endl;
 | |
| 	      aligned->T::~T();
 | |
| 	    }
 | |
| 	}
 | |
|       private:
 | |
| 	typedef typename add_reference<typename add_cv<T>::type>::type ref_type;
 | |
|       };
 | |
| 
 | |
| 
 | |
|       
 | |
| 
 | |
| 
 | |
|       // Used when T is a plain value (non-pointer, non-reference) type or
 | |
|       // a (non-volatile) const reference to a plain value type.
 | |
|       template<typename S, int A, int B, int C, int D, int E>
 | |
|       struct arg_rvalue_from_python< Eigen::Matrix<S,A,B,C,D,E> >
 | |
|       {
 | |
| 	typedef Eigen::Matrix<S,A,B,C,D,E> const & T;
 | |
| 	typedef typename boost::add_reference<
 | |
| 	  T
 | |
| 	  // We can't add_const here, or it would be impossible to pass
 | |
| 	  // auto_ptr<U> args from Python to C++
 | |
| 	  >::type result_type;
 | |
| 	
 | |
| 	arg_rvalue_from_python(PyObject * obj) : m_data(converter::rvalue_from_python_stage1(obj, registered<T>::converters))
 | |
| 					       , m_source(obj)
 | |
| 	{
 | |
| 	  
 | |
| 	}
 | |
| 	bool convertible() const
 | |
| 	{
 | |
| 	  return m_data.stage1.convertible != 0;
 | |
| 	}
 | |
| 
 | |
| 	
 | |
| # if BOOST_MSVC < 1301 || _MSC_FULL_VER > 13102196
 | |
| 	typename arg_rvalue_from_python<T>::
 | |
| # endif 
 | |
| 	result_type operator()()
 | |
| 	{
 | |
| 	  if (m_data.stage1.construct != 0)
 | |
| 	    m_data.stage1.construct(m_source, &m_data.stage1);
 | |
| 	  
 | |
| 	  // Here is the magic...
 | |
| 	  // Realign the pointer
 | |
| 	  void * storage = reinterpret_cast<void *>(m_data.storage.bytes);
 | |
| 	  void * aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(storage) & ~(size_t(15))) + 16);
 | |
| 	  
 | |
| 	  return python::detail::void_ptr_to_reference(aligned, (result_type(*)())0);
 | |
| 	}
 | |
| 
 | |
|       private:
 | |
| 	rvalue_from_python_data<result_type> m_data;
 | |
| 	PyObject* m_source;
 | |
|       };
 | |
| 
 | |
| 
 | |
|       // Used when T is a plain value (non-pointer, non-reference) type or
 | |
|       // a (non-volatile) const reference to a plain value type.
 | |
|       template<typename S, int A, int B, int C, int D, int E>
 | |
|       struct arg_rvalue_from_python< Eigen::Matrix<S,A,B,C,D,E> const & >
 | |
|       {
 | |
| 	typedef Eigen::Matrix<S,A,B,C,D,E> const & T;
 | |
| 	typedef typename boost::add_reference<
 | |
| 	  T
 | |
| 	  // We can't add_const here, or it would be impossible to pass
 | |
| 	  // auto_ptr<U> args from Python to C++
 | |
| 	  >::type result_type;
 | |
| 	
 | |
| 	arg_rvalue_from_python(PyObject * obj) : m_data(converter::rvalue_from_python_stage1(obj, registered<T>::converters))
 | |
| 					       , m_source(obj)
 | |
| 	{
 | |
| 	  
 | |
| 	}
 | |
| 	bool convertible() const
 | |
| 	{
 | |
| 	  return m_data.stage1.convertible != 0;
 | |
| 	}
 | |
| 
 | |
| 	
 | |
| # if BOOST_MSVC < 1301 || _MSC_FULL_VER > 13102196
 | |
| 	typename arg_rvalue_from_python<T>::
 | |
| # endif 
 | |
| 	result_type operator()()
 | |
| 	{
 | |
| 	  if (m_data.stage1.construct != 0)
 | |
| 	    m_data.stage1.construct(m_source, &m_data.stage1);
 | |
| 	  
 | |
| 	  // Here is the magic...
 | |
| 	  // Realign the pointer
 | |
| 	  void * storage = reinterpret_cast<void *>(m_data.storage.bytes);
 | |
| 	  void * aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(storage) & ~(size_t(15))) + 16);
 | |
| 	  
 | |
| 	  return python::detail::void_ptr_to_reference(aligned, (result_type(*)())0);
 | |
| 	}
 | |
| 
 | |
|       private:
 | |
| 	rvalue_from_python_data<result_type> m_data;
 | |
| 	PyObject* m_source;
 | |
|       };
 | |
| 
 | |
|       // Used when T is a plain value (non-pointer, non-reference) type or
 | |
|       // a (non-volatile) const reference to a plain value type.
 | |
|       template<typename S, int A, int B, int C, int D, int E>
 | |
|       struct arg_rvalue_from_python< Eigen::Matrix<S,A,B,C,D,E> const >
 | |
|       {
 | |
| 	typedef Eigen::Matrix<S,A,B,C,D,E> const & T;
 | |
| 	typedef typename boost::add_reference<
 | |
| 	  T
 | |
| 	  // We can't add_const here, or it would be impossible to pass
 | |
| 	  // auto_ptr<U> args from Python to C++
 | |
| 	  >::type result_type;
 | |
| 	
 | |
| 	arg_rvalue_from_python(PyObject * obj) : m_data(converter::rvalue_from_python_stage1(obj, registered<T>::converters))
 | |
| 					       , m_source(obj)
 | |
| 	{
 | |
| 	  
 | |
| 	}
 | |
| 	bool convertible() const
 | |
| 	{
 | |
| 	  return m_data.stage1.convertible != 0;
 | |
| 	}
 | |
| 
 | |
| 	
 | |
| # if BOOST_MSVC < 1301 || _MSC_FULL_VER > 13102196
 | |
| 	typename arg_rvalue_from_python<T>::
 | |
| # endif 
 | |
| 	result_type operator()()
 | |
| 	{
 | |
| 	  if (m_data.stage1.construct != 0)
 | |
| 	    m_data.stage1.construct(m_source, &m_data.stage1);
 | |
| 	  
 | |
| 	  // Here is the magic...
 | |
| 	  // Realign the pointer
 | |
| 	  void * storage = reinterpret_cast<void *>(m_data.storage.bytes);
 | |
| 	  void * aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(storage) & ~(size_t(15))) + 16);
 | |
| 	  
 | |
| 	  return python::detail::void_ptr_to_reference(aligned, (result_type(*)())0);
 | |
| 	}
 | |
| 
 | |
|       private:
 | |
| 	rvalue_from_python_data<result_type> m_data;
 | |
| 	PyObject* m_source;
 | |
|       };
 | |
| 
 | |
| 
 | |
|     }}}
 | |
| 
 | |
| 
 | |
| #endif /* NUMPY_EIGEN_CONVERTERS_HPP */
 |