mirror of
https://github.com/boostorg/python.git
synced 2026-01-20 16:52:15 +00:00
class_<> is now derived from object
[SVN r14594]
This commit is contained in:
@@ -47,14 +47,14 @@ namespace detail
|
||||
// to the type of holder that must be created. The 3rd argument is a
|
||||
// reference to the Python type object to be created.
|
||||
template <class T, class Holder>
|
||||
static inline void register_copy_constructor(mpl::bool_t<true> const&, Holder*, handle<> const& obj, T* = 0)
|
||||
static inline void register_copy_constructor(mpl::bool_t<true> const&, Holder*, object const& obj, T* = 0)
|
||||
{
|
||||
objects::class_wrapper<T,Holder> x(obj);
|
||||
}
|
||||
|
||||
// Tag dispatched to have no effect.
|
||||
template <class T, class Holder>
|
||||
static inline void register_copy_constructor(mpl::bool_t<false> const&, Holder*, handle<> const&, T* = 0)
|
||||
static inline void register_copy_constructor(mpl::bool_t<false> const&, Holder*, object const&, T* = 0)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -104,11 +104,13 @@ class class_ : public objects::class_base
|
||||
// Use function::add_to_namespace to achieve overloading if
|
||||
// appropriate.
|
||||
objects::function::add_to_namespace(
|
||||
this->object(), name,
|
||||
handle<>(detail::wrap_function(
|
||||
*this, name
|
||||
, object(
|
||||
detail::new_reference(
|
||||
detail::wrap_function(
|
||||
// This bit of nastiness casts F to a member function of T if possible.
|
||||
detail::member_function_cast<T,F>::stage1(f).stage2((T*)0).stage3(f)
|
||||
)));
|
||||
))));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -132,8 +134,10 @@ class class_ : public objects::class_base
|
||||
// Use function::add_to_namespace to achieve overloading if
|
||||
// appropriate.
|
||||
objects::function::add_to_namespace(
|
||||
this->object(), op.name(),
|
||||
handle<>(detail::wrap_function(&op_t::template apply<T>::execute)));
|
||||
*this, op.name()
|
||||
, object(
|
||||
detail::new_reference(
|
||||
detail::wrap_function(&op_t::template apply<T>::execute))));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -255,7 +259,7 @@ inline class_<T,X1,X2,X3>::class_()
|
||||
detail::register_copy_constructor<T>(
|
||||
mpl::bool_t<is_copyable>()
|
||||
, objects::select_holder<T,held_type>((held_type*)0).get()
|
||||
, this->object());
|
||||
, *this);
|
||||
}
|
||||
|
||||
template <class T, class X1, class X2, class X3>
|
||||
@@ -268,7 +272,7 @@ inline class_<T,X1,X2,X3>::class_(char const* name)
|
||||
detail::register_copy_constructor<T>(
|
||||
mpl::bool_t<is_copyable>()
|
||||
, objects::select_holder<T,held_type>((held_type*)0).get()
|
||||
, this->object());
|
||||
, *this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
# include <boost/python/detail/target.hpp>
|
||||
# include <boost/python/object/iterator.hpp>
|
||||
# include <boost/python/object_core.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
|
||||
@@ -19,7 +20,7 @@ namespace detail
|
||||
// objects::make_iterator(...), which allows us to pass member
|
||||
// function and member data pointers.
|
||||
template <class NextPolicies, class Target, class Accessor1, class Accessor2>
|
||||
inline handle<> make_iterator(
|
||||
inline object make_iterator(
|
||||
Accessor1 get_start, Accessor2 get_finish, boost::type<Target>* target = 0, NextPolicies* = 0)
|
||||
{
|
||||
return objects::make_iterator_function<NextPolicies,Target>(
|
||||
@@ -70,9 +71,14 @@ struct iterators
|
||||
template <class Accessor1, class Accessor2>
|
||||
handle<> range(Accessor1 start, Accessor2 finish)
|
||||
{
|
||||
return detail::make_iterator<objects::default_iterator_call_policies>(
|
||||
start, finish
|
||||
, detail::target(start));
|
||||
return handle<>(
|
||||
borrowed(allow_null(
|
||||
detail::make_iterator<objects::default_iterator_call_policies>(
|
||||
start, finish
|
||||
, detail::target(start))
|
||||
.ptr()
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
// Create an iterator-building function which uses the given accessors
|
||||
@@ -80,7 +86,12 @@ handle<> range(Accessor1 start, Accessor2 finish)
|
||||
template <class NextPolicies, class Accessor1, class Accessor2>
|
||||
handle<> range(Accessor1 start, Accessor2 finish, NextPolicies* = 0)
|
||||
{
|
||||
return detail::make_iterator<NextPolicies>(start, finish, detail::target(start));
|
||||
return handle<>(
|
||||
borrowed(
|
||||
allow_null(
|
||||
detail::make_iterator<NextPolicies>(start, finish, detail::target(start))
|
||||
.ptr()
|
||||
)));
|
||||
}
|
||||
|
||||
// Create an iterator-building function which uses the given accessors
|
||||
@@ -89,7 +100,12 @@ template <class NextPolicies, class Target, class Accessor1, class Accessor2>
|
||||
handle<> range(Accessor1 start, Accessor2 finish, NextPolicies* = 0, boost::type<Target>* = 0)
|
||||
{
|
||||
typedef typename add_reference<Target>::type target;
|
||||
return detail::make_iterator<NextPolicies, target>(start, finish);
|
||||
return handle<>(
|
||||
borrowed(
|
||||
allow_null(
|
||||
detail::make_iterator<NextPolicies, target>(start, finish)
|
||||
.ptr()
|
||||
)));
|
||||
}
|
||||
|
||||
// A Python callable object which produces an iterator traversing
|
||||
|
||||
@@ -32,7 +32,7 @@ class module : public detail::module_base
|
||||
template <class T1, class T2 , class T3, class T4>
|
||||
module& add(class_<T1,T2,T3,T4> const& c)
|
||||
{
|
||||
this->add_class(c.object());
|
||||
this->add_class(type_handle(borrowed((PyTypeObject*)c.ptr())));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
# include <boost/python/instance_holder.hpp>
|
||||
# include <boost/python/object_core.hpp>
|
||||
# include <cstddef>
|
||||
|
||||
namespace boost { namespace python {
|
||||
@@ -23,7 +24,7 @@ namespace objects {
|
||||
// To identify a class, we don't need cv/reference decorations
|
||||
typedef type_info class_id;
|
||||
|
||||
struct BOOST_PYTHON_DECL class_base : private noncopyable
|
||||
struct BOOST_PYTHON_DECL class_base : python::api::object
|
||||
{
|
||||
// constructor
|
||||
class_base(
|
||||
@@ -35,13 +36,10 @@ struct BOOST_PYTHON_DECL class_base : private noncopyable
|
||||
);
|
||||
|
||||
// Retrieve the underlying object
|
||||
type_handle object() const { return m_object; }
|
||||
void add_property(char const* name, handle<> const& fget);
|
||||
void add_property(char const* name, handle<> const& fget, handle<> const& fset);
|
||||
void setattr(char const* name, handle<> const&);
|
||||
void enable_pickling(bool getstate_manages_dict);
|
||||
private:
|
||||
type_handle m_object;
|
||||
};
|
||||
|
||||
BOOST_PYTHON_DECL type_handle registered_class_object(class_id id);
|
||||
|
||||
@@ -15,11 +15,11 @@ template <class T, class Holder>
|
||||
struct class_wrapper
|
||||
: to_python_converter<T,class_wrapper<T,Holder> >
|
||||
{
|
||||
class_wrapper(handle<> const& type_)
|
||||
class_wrapper(object const& type_)
|
||||
: m_class_object_keeper(type_)
|
||||
{
|
||||
assert(type_->ob_type == (PyTypeObject*)class_metatype().get());
|
||||
m_class_object = (PyTypeObject*)type_.get();
|
||||
assert(type_.ptr()->ob_type == (PyTypeObject*)class_metatype().get());
|
||||
m_class_object = (PyTypeObject*)type_.ptr();
|
||||
}
|
||||
|
||||
static PyObject* convert(T const& x)
|
||||
@@ -48,7 +48,7 @@ struct class_wrapper
|
||||
}
|
||||
|
||||
private:
|
||||
handle<> m_class_object_keeper;
|
||||
object m_class_object_keeper;
|
||||
static PyTypeObject* m_class_object;
|
||||
};
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
# include <boost/function/function2.hpp>
|
||||
# include <boost/python/object_fwd.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
@@ -27,7 +28,7 @@ struct BOOST_PYTHON_DECL function : PyObject
|
||||
// a function object (this class), and an existing function is
|
||||
// already there, add it as an overload.
|
||||
static void add_to_namespace(
|
||||
handle<> const& name_space, char const* name, handle<> const& attribute);
|
||||
object const& name_space, char const* name, object const& attribute);
|
||||
|
||||
private: // helper functions
|
||||
void argument_error(PyObject* args, PyObject* keywords) const;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
# include <boost/mpl/apply.hpp>
|
||||
# include <boost/bind.hpp>
|
||||
# include <boost/bind/protect.hpp>
|
||||
# include <boost/python/detail/raw_pyobject.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
@@ -113,30 +114,28 @@ namespace detail
|
||||
// policies, creating it if neccessary. Requires: NextPolicies is
|
||||
// default-constructible.
|
||||
template <class Iterator, class NextPolicies>
|
||||
handle<> demand_iterator_class(char const* name, Iterator* = 0, NextPolicies const& policies = NextPolicies())
|
||||
object 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.
|
||||
handle<> result(
|
||||
handle<> class_obj(
|
||||
objects::registered_class_object(python::type_id<range_>()));
|
||||
|
||||
if (result.get() == 0)
|
||||
{
|
||||
// Make a callable object which can be used as the iterator's next() function.
|
||||
handle<> 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();
|
||||
if (class_obj.get() != 0)
|
||||
return object(class_obj);
|
||||
|
||||
}
|
||||
return result;
|
||||
// Make a callable object which can be used as the iterator's next() function.
|
||||
handle<> next_function(
|
||||
new objects::function(
|
||||
objects::py_function(
|
||||
bind(&detail::iterator_next<Iterator,NextPolicies>::execute, _1, _2, policies))
|
||||
, 1));
|
||||
|
||||
return class_<range_>(name)
|
||||
.def("__iter__", identity_function())
|
||||
.setattr("next", next_function)
|
||||
;
|
||||
}
|
||||
|
||||
// This class template acts as a generator for an ordinary function
|
||||
@@ -187,22 +186,23 @@ namespace detail
|
||||
// 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 handle<> make_iterator_function(
|
||||
inline object make_iterator_function(
|
||||
Accessor1 const& get_start, Accessor2 const& get_finish
|
||||
, boost::type<Target>* = 0, NextPolicies* = 0)
|
||||
{
|
||||
typedef typename Accessor1::result_type result_type;
|
||||
|
||||
return handle<>(
|
||||
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 ));
|
||||
return object(
|
||||
python::detail::new_non_null_reference(
|
||||
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 ))
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
# include <boost/type.hpp>
|
||||
|
||||
# include <boost/python/object/class.hpp>
|
||||
# include <boost/python/instance_holder.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/object/inheritance.hpp>
|
||||
# include <boost/python/object/find_instance.hpp>
|
||||
|
||||
17
include/boost/python/object_fwd.hpp
Normal file
17
include/boost/python/object_fwd.hpp
Normal file
@@ -0,0 +1,17 @@
|
||||
// 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 OBJECT_FWD_DWA2002724_HPP
|
||||
# define OBJECT_FWD_DWA2002724_HPP
|
||||
|
||||
namespace boost { namespace python {
|
||||
namespace api
|
||||
{
|
||||
class object;
|
||||
}
|
||||
using api::object;
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // OBJECT_FWD_DWA2002724_HPP
|
||||
@@ -37,7 +37,7 @@ void module_base::setattr(char const* name, handle<> const& x)
|
||||
{
|
||||
// Use function::add_to_namespace to achieve overloading if
|
||||
// appropriate.
|
||||
objects::function::add_to_namespace(m_module, name, x);
|
||||
objects::function::add_to_namespace(python::object(m_module), name, python::object(x));
|
||||
}
|
||||
|
||||
void module_base::add(type_handle const& x)
|
||||
|
||||
@@ -243,9 +243,12 @@ namespace objects
|
||||
// corresponding to the class being created, and the
|
||||
// rest corresponding to its declared bases.
|
||||
//
|
||||
class_base::class_base(
|
||||
char const* name, std::size_t num_types, class_id const* const types)
|
||||
|
||||
namespace
|
||||
{
|
||||
inline object
|
||||
new_class(char const* name, std::size_t num_types, class_id const* const types)
|
||||
{
|
||||
assert(num_types >= 1);
|
||||
|
||||
// Build a tuple of the base Python type objects. If no bases
|
||||
@@ -271,14 +274,20 @@ namespace objects
|
||||
// Call the class metatype to create a new class
|
||||
PyObject* c = PyObject_CallObject(upcast<PyObject>(class_metatype().get()), args.get());
|
||||
assert(PyType_IsSubtype(c->ob_type, &PyType_Type));
|
||||
m_object = type_handle((PyTypeObject*)c);
|
||||
|
||||
return object(python::detail::new_reference(c));
|
||||
}
|
||||
}
|
||||
|
||||
class_base::class_base(
|
||||
char const* name, std::size_t num_types, class_id const* const types)
|
||||
: object(new_class(name, num_types, types))
|
||||
{
|
||||
// Insert the new class object in the registry
|
||||
converter::registration& converters = const_cast<converter::registration&>(
|
||||
converter::registry::lookup(types[0]));
|
||||
|
||||
// Class object is leaked, for now
|
||||
converters.class_object = (PyTypeObject*)incref(m_object.get());
|
||||
converters.class_object = (PyTypeObject*)incref(this->ptr());
|
||||
}
|
||||
|
||||
extern "C"
|
||||
@@ -301,7 +310,7 @@ namespace objects
|
||||
|
||||
void class_base::setattr(char const* name, handle<> const& x)
|
||||
{
|
||||
if (PyObject_SetAttrString(upcast<PyObject>(object().get()), const_cast<char*>(name), x.get()) < 0)
|
||||
if (PyObject_SetAttrString(this->ptr(), const_cast<char*>(name), x.get()) < 0)
|
||||
throw_error_already_set();
|
||||
}
|
||||
|
||||
@@ -317,7 +326,7 @@ namespace objects
|
||||
|
||||
BOOST_PYTHON_DECL type_handle registered_class_object(class_id id)
|
||||
{
|
||||
return objects::query_class(id);
|
||||
return query_class(id);
|
||||
}
|
||||
} // namespace objects
|
||||
|
||||
|
||||
@@ -156,12 +156,12 @@ namespace
|
||||
}
|
||||
|
||||
void function::add_to_namespace(
|
||||
handle<> const& name_space, char const* name_, handle<> const& attribute)
|
||||
object const& name_space, char const* name_, object const& attribute)
|
||||
{
|
||||
str const name(name_);
|
||||
PyObject* const ns = name_space.get();
|
||||
PyObject* const ns = name_space.ptr();
|
||||
|
||||
if (attribute->ob_type == &function_type)
|
||||
if (attribute.ptr()->ob_type == &function_type)
|
||||
{
|
||||
PyObject* dict = 0;
|
||||
|
||||
@@ -175,27 +175,27 @@ void function::add_to_namespace(
|
||||
if (dict == 0)
|
||||
throw_error_already_set();
|
||||
|
||||
handle<> existing( allow_null(PyObject_GetItem(dict, name.ptr())) );
|
||||
handle<> existing( allow_null(::PyObject_GetItem(dict, name.ptr())) );
|
||||
|
||||
if (existing.get())
|
||||
{
|
||||
if (existing->ob_type == &function_type)
|
||||
{
|
||||
static_cast<function*>(attribute.get())->add_overload(
|
||||
static_cast<function*>(attribute.ptr())->add_overload(
|
||||
static_cast<function*>(existing.get()));
|
||||
}
|
||||
}
|
||||
// Binary operators need an additional overload which returns NotImplemented
|
||||
else if (is_binary_operator(name_))
|
||||
{
|
||||
static_cast<function*>(attribute.get())->add_overload(
|
||||
static_cast<function*>(attribute.ptr())->add_overload(
|
||||
not_implemented_function());
|
||||
}
|
||||
}
|
||||
|
||||
// The PyObject_GetAttrString() call above left an active error
|
||||
PyErr_Clear();
|
||||
if (PyObject_SetAttr(ns, name.ptr(), attribute.get()) < 0)
|
||||
if (PyObject_SetAttr(ns, name.ptr(), attribute.ptr()) < 0)
|
||||
throw_error_already_set();
|
||||
}
|
||||
|
||||
|
||||
@@ -120,9 +120,7 @@ BOOST_PYTHON_MODULE_INIT(extract_ext)
|
||||
;
|
||||
|
||||
// Instantiate an X object through the Python interface
|
||||
type_handle xc1 = x_class.object();
|
||||
object X_(xc1);
|
||||
object x_obj = X_(3);
|
||||
object x_obj = x_class(3);
|
||||
|
||||
// Get the C++ object out of the Python object
|
||||
X const& x = extract<X&>(x_obj);
|
||||
|
||||
Reference in New Issue
Block a user