Package pyplusplus :: Package code_repository :: Module return_range

Source Code for Module pyplusplus.code_repository.return_range

  1  # Copyright 2004-2008 Roman Yakovenko.
 
  2  # Distributed under the Boost Software License, Version 1.0. (See
 
  3  # accompanying file LICENSE_1_0.txt or copy at
 
  4  # http://www.boost.org/LICENSE_1_0.txt)
 
  5  
 
  6  """
 
  7  This file contains C++ code - "return_range" call policies
 
  8  """ 
  9  
 
 10  from pyplusplus.decl_wrappers import call_policies 
 11  
 
 12  namespace = "pyplusplus::call_policies" 
 13  
 
 14  file_name = call_policies.return_range_t.HEADER_FILE 
 15  
 
 16  code = \
 
 17  """// Copyright 2004-2008 Roman Yakovenko.
 
 18  // Distributed under the Boost Software License, Version 1.0. (See
 
 19  // accompanying file LICENSE_1_0.txt or copy at
 
 20  // http://www.boost.org/LICENSE_1_0.txt)
 
 21  
 
 22  #ifndef return_range_pyplusplus_hpp__
 
 23  #define return_range_pyplusplus_hpp__
 
 24  
 
 25  #include "boost/python.hpp"
 
 26  #include "boost/mpl/int.hpp"
 
 27  #include "boost/function.hpp"
 
 28  #include "boost/python/suite/indexing/iterator_range.hpp"
 
 29  #include "boost/python/object/class_detail.hpp"
 
 30  #include "boost/type_traits/is_same.hpp"
 
 31  namespace pyplusplus{ namespace call_policies{
 
 32  
 
 33  namespace bpl = boost::python;
 
 34  
 
 35  namespace detail{  
 
 36  
 
 37  struct return_raw_data_ref{
 
 38      
 
 39      template <class T> 
 
 40      struct apply{
 
 41  
 
 42          BOOST_STATIC_ASSERT( boost::is_pointer<T>::value );
 
 43          
 
 44          struct type{
 
 45              static bool convertible()
 
 46              { return true; }
 
 47  
 
 48              PyObject* 
 
 49              operator()( T return_value) const{ 
 
 50                  if( !return_value ){
 
 51                      return bpl::detail::none();
 
 52                  }
 
 53                  else{
 
 54                      typedef typename boost::remove_pointer< T >::type value_type;
 
 55                      typedef typename boost::remove_const< value_type >::type non_const_value_type;
 
 56                      non_const_value_type* data = const_cast<non_const_value_type*>( return_value );
 
 57                      return PyCObject_FromVoidPtr( data, NULL ); 
 
 58                  }
 
 59              }
 
 60          };
 
 61  
 
 62      };
 
 63  
 
 64  };
 
 65  
 
 66  } //detail
 
 67      
 
 68  template < typename TGetSize, typename TValueType, typename TValuePolicies=bpl::default_call_policies > 
 
 69  struct return_range : bpl::default_call_policies{
 
 70  
 
 71      typedef return_range< TGetSize, TValueType, TValuePolicies > this_type;
 
 72  
 
 73  public:
 
 74  
 
 75      typedef typename detail::return_raw_data_ref result_converter;
 
 76      
 
 77      typedef TValueType value_type;
 
 78      typedef TGetSize get_size_type;
 
 79      typedef TValuePolicies value_policies_type;
 
 80      
 
 81      typedef bpl::indexing::iterator_range<value_type*> range_type;
 
 82  
 
 83      template <class ArgumentPackage>
 
 84      static PyObject* postcall(ArgumentPackage const& args, PyObject* result){
 
 85          if( result == bpl::detail::none() ){
 
 86              return result;
 
 87          }
 
 88          if( !PyCObject_Check( result ) ){
 
 89              throw std::runtime_error( "Internal error: expected to get PyCObject" );
 
 90          }
 
 91          value_type* raw_data = reinterpret_cast<value_type*>( PyCObject_AsVoidPtr( result ) );
 
 92          Py_DECREF(result);//we don't need result anymore
 
 93          
 
 94          bpl::tuple args_w( bpl::handle<>( bpl::borrowed( args ) ) );
 
 95  
 
 96          register_range_class_on_demand();
 
 97          
 
 98          get_size_type get_size;
 
 99          range_type the_range( raw_data, raw_data + get_size( args_w ) );
 
100          
 
101          bpl::object range_obj( the_range );
 
102          
 
103          return bpl::incref( range_obj.ptr() );
 
104      }
 
105  private:
 
106  
 
107      static void register_range_class( boost::mpl::true_ ){
 
108          //register range class with default call policies
 
109          bpl::class_<range_type>( "_impl_details_range_iterator_",  bpl::init<value_type*, value_type*>() )
 
110              .def(bpl::indexing::container_suite<range_type>() );
 
111      }
 
112      
 
113      static void register_range_class( boost::mpl::false_ ){
 
114          //register range class with non default call policies
 
115          unsigned long const methods_mask 
 
116              = bpl::indexing::all_methods 
 
117                & ~( bpl::indexing::reorder_methods |  bpl::indexing::search_methods ) ;
 
118  
 
119          typedef bpl::indexing::iterator_range_suite< range_type, methods_mask > suite_type;
 
120          bpl::class_<range_type>( "_impl_details_range_iterator_",  bpl::init<value_type*, value_type*>() )
 
121              .def( suite_type::with_policies( value_policies_type() ) );
 
122      }
 
123  
 
124      static void register_range_class_on_demand(){
 
125          //Check the registry. If the class doesn't exist, register it.
 
126          bpl::handle<> class_obj(
 
127              bpl::objects::registered_class_object(bpl::type_id<range_type>()));
 
128          
 
129          if( class_obj.get() == 0 ){
 
130              register_range_class( boost::is_same< bpl::default_call_policies, value_policies_type>() );
 
131          }
 
132      }
 
133  
 
134  };
 
135  
 
136  } /*pyplusplus*/ } /*call_policies*/
 
137  
 
138  
 
139  #endif//return_range_pyplusplus_hpp__
 
140  
 
141  """ 
142