2
0
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:
Dave Abrahams
2002-07-25 04:41:21 +00:00
parent f458dbdbcb
commit 63eed8994a
13 changed files with 115 additions and 72 deletions

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
};

View File

@@ -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;

View File

@@ -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 ))
);
}
//

View File

@@ -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>

View 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

View File

@@ -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)

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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);