1
2
3
4
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