mirror of
https://github.com/boostorg/python.git
synced 2026-01-19 16:32:16 +00:00
initial commit
[SVN r13837]
This commit is contained in:
89
include/boost/python/detail/target.hpp
Normal file
89
include/boost/python/detail/target.hpp
Normal file
@@ -0,0 +1,89 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef TARGET_DWA2002513_HPP
|
||||
# define TARGET_DWA2002513_HPP
|
||||
|
||||
# include <boost/type.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
//
|
||||
// target(x) - deduce the type of the first argument when bind(x) is
|
||||
// invoked.
|
||||
//
|
||||
|
||||
// functions
|
||||
template <class Target, class R>
|
||||
boost::type<Target>* target(R (*)(Target)) { return 0; }
|
||||
|
||||
template <class Target, class R, class A1>
|
||||
boost::type<Target>* target(R (*)(Target, A1)) { return 0; }
|
||||
|
||||
template <class Target, class R, class A1, class A2>
|
||||
boost::type<Target>* target(R (*)(Target, A1, A2)) { return 0; }
|
||||
|
||||
template <class Target, class R, class A1, class A2, class A3>
|
||||
boost::type<Target>* target(R (*)(Target, A1, A2, A3)) { return 0; }
|
||||
|
||||
// data member pointers
|
||||
template <class Target, class R>
|
||||
boost::type<Target&>* target(R (Target::*)) { return 0; }
|
||||
|
||||
// member Functions
|
||||
template <class Target, class R>
|
||||
boost::type<Target&>* target(R (Target::*)()) { return 0; }
|
||||
|
||||
template <class Target, class R, class A1>
|
||||
boost::type<Target&>* target(R (Target::*)(A1)) { return 0; }
|
||||
|
||||
template <class Target, class R, class A1, class A2>
|
||||
boost::type<Target&>* target(R (Target::*)(A1,A2)) { return 0; }
|
||||
|
||||
template <class Target, class R, class A1, class A2, class A3>
|
||||
boost::type<Target&>* target(R (Target::*)(A1,A2,A3)) { return 0; }
|
||||
|
||||
// const member functions
|
||||
template <class Target, class R>
|
||||
boost::type<Target const&>* target(R (Target::*)() const) { return 0; }
|
||||
|
||||
template <class Target, class R, class A1>
|
||||
boost::type<Target const&>* target(R (Target::*)(A1) const) { return 0; }
|
||||
|
||||
template <class Target, class R, class A1, class A2>
|
||||
boost::type<Target const&>* target(R (Target::*)(A1,A2) const) { return 0; }
|
||||
|
||||
template <class Target, class R, class A1, class A2, class A3>
|
||||
boost::type<Target const&>* target(R (Target::*)(A1,A2,A3) const) { return 0; }
|
||||
|
||||
// volatile member functions
|
||||
template <class Target, class R>
|
||||
boost::type<Target volatile&>* target(R (Target::*)() volatile) { return 0; }
|
||||
|
||||
template <class Target, class R, class A1>
|
||||
boost::type<Target volatile&>* target(R (Target::*)(A1) volatile) { return 0; }
|
||||
|
||||
template <class Target, class R, class A1, class A2>
|
||||
boost::type<Target volatile&>* target(R (Target::*)(A1,A2) volatile) { return 0; }
|
||||
|
||||
template <class Target, class R, class A1, class A2, class A3>
|
||||
boost::type<Target volatile&>* target(R (Target::*)(A1,A2,A3) volatile) { return 0; }
|
||||
|
||||
// const volatile member functions
|
||||
template <class Target, class R>
|
||||
boost::type<Target const volatile&>* target(R (Target::*)() const volatile) { return 0; }
|
||||
|
||||
template <class Target, class R, class A1>
|
||||
boost::type<Target const volatile&>* target(R (Target::*)(A1) const volatile) { return 0; }
|
||||
|
||||
template <class Target, class R, class A1, class A2>
|
||||
boost::type<Target const volatile&>* target(R (Target::*)(A1,A2) const volatile) { return 0; }
|
||||
|
||||
template <class Target, class R, class A1, class A2, class A3>
|
||||
boost::type<Target const volatile&>* target(R (Target::*)(A1,A2,A3) const volatile) { return 0; }
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // TARGET_DWA2002513_HPP
|
||||
114
include/boost/python/iterator.hpp
Normal file
114
include/boost/python/iterator.hpp
Normal file
@@ -0,0 +1,114 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef ITERATOR_DWA2002512_HPP
|
||||
# define ITERATOR_DWA2002512_HPP
|
||||
|
||||
# include <boost/python/detail/target.hpp>
|
||||
# include <boost/python/object/iterator.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Adds an additional layer of binding to
|
||||
// objects::make_iterator(...), which allows us to pass member
|
||||
// function and member data pointers.
|
||||
template <class Target, class NextPolicies, class Accessor1, class Accessor2>
|
||||
inline ref make_iterator(
|
||||
Accessor1 get_start, Accessor2 get_finish, NextPolicies* = 0, boost::type<Target>* target = 0)
|
||||
{
|
||||
return objects::make_iterator_function(
|
||||
boost::protect(boost::bind(get_start, _1))
|
||||
, boost::protect(boost::bind(get_finish, _1))
|
||||
, (NextPolicies*)0
|
||||
, target);
|
||||
}
|
||||
|
||||
// Guts of template class iterators<>, below.
|
||||
template <bool const_ = false>
|
||||
struct iterators_impl
|
||||
{
|
||||
template <class T>
|
||||
struct apply
|
||||
{
|
||||
typedef typename T::iterator iterator;
|
||||
static iterator begin(T& x) { return x.begin(); }
|
||||
static iterator end(T& x) { return x.end(); }
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct iterators_impl<true>
|
||||
{
|
||||
template <class T>
|
||||
struct apply
|
||||
{
|
||||
typedef typename T::const_iterator iterator;
|
||||
static iterator begin(T& x) { return x.begin(); }
|
||||
static iterator end(T& x) { return x.end(); }
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// An "ordinary function generator" which contains static begin(x) and
|
||||
// end(x) functions that invoke T::begin() and T::end(), respectively.
|
||||
template <class T>
|
||||
struct iterators
|
||||
: detail::iterators_impl<
|
||||
boost::is_const<T>::value
|
||||
>::template apply<T>
|
||||
{
|
||||
};
|
||||
|
||||
// Create an iterator-building function which uses the given
|
||||
// accessors. Deduce the Target type from the accessors. The iterator
|
||||
// returns copies of the inderlying elements.
|
||||
template <class Accessor1, class Accessor2>
|
||||
ref range(Accessor1 start, Accessor2 finish)
|
||||
{
|
||||
return detail::make_iterator(start, finish, (objects::default_iterator_call_policies*)0, detail::target(start));
|
||||
}
|
||||
|
||||
// Create an iterator-building function which uses the given accessors
|
||||
// and next() policies. Deduce the Target type.
|
||||
template <class NextPolicies, class Accessor1, class Accessor2>
|
||||
ref range(Accessor1 start, Accessor2 finish, NextPolicies* = 0)
|
||||
{
|
||||
return detail::make_iterator(start, finish, (NextPolicies*)0, detail::target(start));
|
||||
}
|
||||
|
||||
// Create an iterator-building function which uses the given accessors
|
||||
// and next() policies, operating on the given Target type
|
||||
template <class NextPolicies, class Target, class Accessor1, class Accessor2>
|
||||
ref range(Accessor1 start, Accessor2 finish, NextPolicies* = 0, boost::type<Target>* = 0)
|
||||
{
|
||||
typedef typename add_reference<Target>::type target;
|
||||
return detail::make_iterator(start, finish, (NextPolicies*)0,
|
||||
(boost::type<target>*)0);
|
||||
}
|
||||
|
||||
// A Python callable object which produces an iterator traversing
|
||||
// [x.begin(), x.end()), where x is an instance of the Container
|
||||
// type. NextPolicies are used as the CallPolicies for the iterator's
|
||||
// next() function.
|
||||
template <class Container
|
||||
, class NextPolicies = objects::default_iterator_call_policies>
|
||||
struct iterator : ref
|
||||
{
|
||||
iterator()
|
||||
: ref(
|
||||
range<NextPolicies>(
|
||||
&iterators<Container>::begin, &iterators<Container>::end
|
||||
))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // ITERATOR_DWA2002512_HPP
|
||||
211
include/boost/python/object/iterator.hpp
Normal file
211
include/boost/python/object/iterator.hpp
Normal file
@@ -0,0 +1,211 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef ITERATOR_DWA2002510_HPP
|
||||
# define ITERATOR_DWA2002510_HPP
|
||||
|
||||
# include <boost/python/object/iterator_core.hpp>
|
||||
# include <boost/python/class_fwd.hpp>
|
||||
# include <boost/python/return_value_policy.hpp>
|
||||
# include <boost/python/copy_const_reference.hpp>
|
||||
# include <boost/python/object/function.hpp>
|
||||
# include <boost/python/reference.hpp>
|
||||
# include <boost/type.hpp>
|
||||
# include <boost/python/from_python.hpp>
|
||||
# include <boost/mpl/apply.hpp>
|
||||
# include <boost/bind.hpp>
|
||||
# include <boost/bind/protect.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
// CallPolicies for the next() method of iterators. We don't want
|
||||
// users to have to explicitly specify that the references returned by
|
||||
// iterators are copied, so we just replace the result_converter from
|
||||
// the default_iterator_call_policies with a permissive one which
|
||||
// always copies the result.
|
||||
struct default_iterator_call_policies
|
||||
: default_call_policies
|
||||
{
|
||||
struct result_converter
|
||||
{
|
||||
template <class R>
|
||||
struct apply
|
||||
{
|
||||
typedef to_python_value<R> type;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// Instantiations of these are wrapped to produce Python iterators.
|
||||
template <class NextPolicies, class Iterator>
|
||||
struct iterator_range
|
||||
{
|
||||
iterator_range(ref sequence, Iterator start, Iterator finish);
|
||||
|
||||
ref m_sequence; // Keeps the sequence alive while iterating.
|
||||
Iterator m_start;
|
||||
Iterator m_finish;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Guts of the iterator's next() function. We can't just wrap an
|
||||
// ordinary function because we don't neccessarily know the result
|
||||
// type of dereferencing the iterator. This also saves us from
|
||||
// throwing C++ exceptions to indicate end-of-sequence.
|
||||
template <class Iterator, class Policies>
|
||||
struct iterator_next
|
||||
{
|
||||
static PyObject* execute(PyObject* args_, PyObject* kw, Policies const& policies)
|
||||
{
|
||||
typedef iterator_range<Policies,Iterator> range_;
|
||||
|
||||
PyObject* py_self = PyTuple_GET_ITEM(args_, 0);
|
||||
from_python<range_*> c0(py_self);
|
||||
range_* self = c0(py_self);
|
||||
|
||||
// Done iterating?
|
||||
if (self->m_start == self->m_finish)
|
||||
{
|
||||
objects::set_stop_iteration_error();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// note: precall happens before we can check for the result
|
||||
// converter in this case, to ensure it happens before the
|
||||
// iterator is dereferenced. However, the arity is 1 so
|
||||
// there's not much risk that this will amount to anything.
|
||||
if (!policies.precall(args_)) return 0;
|
||||
|
||||
PyObject* result = iterator_next::convert_result(*self->m_start);
|
||||
++self->m_start;
|
||||
|
||||
return policies.postcall(args_, result);
|
||||
}
|
||||
private:
|
||||
// Convert the result of dereferencing the iterator. Dispatched
|
||||
// here because we can't neccessarily get the value_type of the
|
||||
// iterator without PTS. This way, we deduce the value type by
|
||||
// dereferencing.
|
||||
template <class ValueType>
|
||||
static PyObject* convert_result(ValueType& x)
|
||||
{
|
||||
typedef typename Policies::result_converter result_converter;
|
||||
typename mpl::apply1<result_converter,ValueType&>::type cr;
|
||||
if (!cr.convertible()) return 0;
|
||||
|
||||
return cr(x);
|
||||
}
|
||||
};
|
||||
|
||||
// Get a Python class which contains the given iterator and
|
||||
// policies, creating it if neccessary. Requires: NextPolicies is
|
||||
// default-constructible.
|
||||
template <class Iterator, class NextPolicies>
|
||||
ref demand_iterator_class(char const* name, Iterator* = 0, NextPolicies const& policies = NextPolicies())
|
||||
{
|
||||
typedef iterator_range<NextPolicies,Iterator> range_;
|
||||
|
||||
// Check the registry. If one is already registered, return it.
|
||||
ref result(
|
||||
objects::registered_class_object(converter::undecorated_type_id<range_>()));
|
||||
|
||||
if (result.get() == 0)
|
||||
{
|
||||
// Make a callable object which can be used as the iterator's next() function.
|
||||
ref next_function(
|
||||
new objects::function(
|
||||
objects::py_function(
|
||||
bind(&detail::iterator_next<Iterator,NextPolicies>::execute, _1, _2, policies))
|
||||
, 1));
|
||||
|
||||
result = class_<range_>(name)
|
||||
.def("__iter__", identity_function())
|
||||
.setattr("next", next_function)
|
||||
.object();
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// This class template acts as a generator for an ordinary function
|
||||
// which builds a Python iterator.
|
||||
template <class Target, class Iterator
|
||||
, class Accessor1, class Accessor2
|
||||
, class NextPolicies
|
||||
>
|
||||
struct make_iterator_help
|
||||
{
|
||||
// Extract an object x of the Target type from the first Python
|
||||
// argument, and invoke get_start(x)/get_finish(x) to produce
|
||||
// iterators, which are used to construct a new iterator_range<>
|
||||
// object that gets wrapped into a Python iterator.
|
||||
static PyObject* create(
|
||||
Accessor1 const& get_start, Accessor2 const& get_finish
|
||||
, PyObject* args_, PyObject* /*kw*/)
|
||||
{
|
||||
// Make sure the Python class is instantiated.
|
||||
demand_iterator_class<Iterator,NextPolicies>("iterator");
|
||||
|
||||
to_python_value<iterator_range<NextPolicies,Iterator> > cr;
|
||||
|
||||
// This check is probably redundant, since we ensure the
|
||||
// type is registered above.
|
||||
if (!cr.convertible())
|
||||
return 0;
|
||||
|
||||
// Extract x from the first argument
|
||||
PyObject* arg0 = PyTuple_GET_ITEM(args_, 0);
|
||||
from_python<Target> c0(arg0);
|
||||
if (!c0.convertible()) return 0;
|
||||
typename from_python<Target>::result_type x = c0(arg0);
|
||||
|
||||
// Build and convert the iterator_range<>.
|
||||
return cr(
|
||||
iterator_range<NextPolicies,Iterator>(
|
||||
ref(arg0, ref::increment_count)
|
||||
, get_start(x), get_finish(x)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Create a Python callable object which accepts a single argument
|
||||
// convertible to the C++ Target type and returns a Python
|
||||
// iterator. The Python iterator uses get_start(x) and get_finish(x)
|
||||
// (where x is an instance of Target) to produce begin and end
|
||||
// iterators for the range, and an instance of NextPolicies is used as
|
||||
// CallPolicies for the Python iterator's next() function.
|
||||
template <class NextPolicies, class Target, class Accessor1, class Accessor2>
|
||||
inline ref make_iterator_function(
|
||||
Accessor1 const& get_start, Accessor2 const& get_finish
|
||||
, NextPolicies* , boost::type<Target>*)
|
||||
{
|
||||
typedef typename Accessor1::result_type result_type;
|
||||
|
||||
return ref(
|
||||
new objects::function(
|
||||
objects::py_function(
|
||||
boost::bind(
|
||||
&detail::make_iterator_help<
|
||||
Target,result_type,Accessor1,Accessor2,NextPolicies
|
||||
>::create
|
||||
, get_start, get_finish, _1, _2)
|
||||
)
|
||||
,1 ));
|
||||
}
|
||||
|
||||
//
|
||||
// implementation
|
||||
//
|
||||
template <class NextPolicies, class Iterator>
|
||||
inline iterator_range<NextPolicies,Iterator>::iterator_range(
|
||||
ref sequence, Iterator start, Iterator finish)
|
||||
: m_sequence(sequence), m_start(start), m_finish(finish)
|
||||
{
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::objects
|
||||
|
||||
#endif // ITERATOR_DWA2002510_HPP
|
||||
18
include/boost/python/object/iterator_core.hpp
Normal file
18
include/boost/python/object/iterator_core.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef ITERATOR_CORE_DWA2002512_HPP
|
||||
# define ITERATOR_CORE_DWA2002512_HPP
|
||||
|
||||
# include <boost/python/reference.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
BOOST_PYTHON_DECL ref identity_function();
|
||||
BOOST_PYTHON_DECL void set_stop_iteration_error();
|
||||
|
||||
}}} // namespace boost::python::object
|
||||
|
||||
#endif // ITERATOR_CORE_DWA2002512_HPP
|
||||
13
test/minimal.cpp
Normal file
13
test/minimal.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#include <boost/python/module.hpp>
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(minimal_ext)
|
||||
{
|
||||
boost::python::module m("minimal_ext");
|
||||
}
|
||||
|
||||
#include "module_tail.cpp"
|
||||
2
test/minimal.py
Normal file
2
test/minimal.py
Normal file
@@ -0,0 +1,2 @@
|
||||
import minimal_ext
|
||||
|
||||
Reference in New Issue
Block a user