From 0389aab0a33211c99fac0986930ab0a037fb74e5 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 22 Jan 2002 19:51:04 +0000 Subject: [PATCH] Nicer syntactic sugar [SVN r12447] --- include/boost/python/class.hpp | 40 +++++++++------- include/boost/python/module.hpp | 67 +++++++++++++++++++++------ include/boost/python/object/class.hpp | 3 +- src/module.cpp | 37 +++++---------- src/object/class.cpp | 8 ++-- 5 files changed, 90 insertions(+), 65 deletions(-) diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 3b20406e..0f8d2a69 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -6,7 +6,6 @@ #ifndef CLASS_DWA200216_HPP # define CLASS_DWA200216_HPP -# include # include # include # include @@ -84,26 +83,26 @@ template < , class Bases = mpl::type_list<>::type , class HolderGenerator = objects::value_holder_generator > -class class_ : objects::class_base +class class_ : private objects::class_base { typedef class_ self; public: - // Construct with the module and automatically derive the class - // name - class_(module&); + // Automatically derive the class name - only works on some + // compilers because type_info::name is sometimes mangled (gcc) + class_(); - // Construct with the module and class name. [ Would have used a - // default argument but gcc-2.95.2 choked on typeid(T).name() as a - // default parameter value] - class_(module&, char const* name); + // Construct with the class name. [ Would have used a default + // argument but gcc-2.95.2 choked on typeid(T).name() as a default + // parameter value] + class_(char const* name); // Wrap a member function or a non-member function which can take // a T, T cv&, or T cv* as its first parameter, or a callable // python object. template - self& def(F f, char const* name) + self& def(char const* name, F f) { // Use function::add_to_namespace to achieve overloading if // appropriate. @@ -117,7 +116,7 @@ class class_ : objects::class_base template self& def_init(Args const& = Args()) { - def(make_constructor(), "__init__"); + def("__init__", make_constructor()); return *this; } @@ -128,6 +127,9 @@ class class_ : objects::class_base return *this; } + // return the underlying object + ref object() const; + private: // types typedef objects::class_id class_id; @@ -160,9 +162,8 @@ class class_ : objects::class_base // implementations // template -inline class_::class_( - module& m) - : class_base(m, typeid(T).name(), id_vector::size, id_vector().ids) +inline class_::class_() + : class_base(typeid(T).name(), id_vector::size, id_vector().ids) { // Bring the class converters into existence. This static object // will survive until the shared library this module lives in is @@ -171,9 +172,8 @@ inline class_::class_( } template -inline class_::class_( - module& m, char const* name) - : class_base(m, name, id_vector::size, id_vector().ids) +inline class_::class_(char const* name) + : class_base(name, id_vector::size, id_vector().ids) { // Bring the class converters into existence. This static object // will survive until the shared library this module lives in is @@ -181,6 +181,12 @@ inline class_::class_( static objects::class_converters converters(object()); } +template +inline ref class_::object() const +{ + return this->class_base::object(); +} + }} // namespace boost::python #endif // CLASS_DWA200216_HPP diff --git a/include/boost/python/module.hpp b/include/boost/python/module.hpp index 318f4a64..a6a3a8e7 100644 --- a/include/boost/python/module.hpp +++ b/include/boost/python/module.hpp @@ -15,6 +15,8 @@ namespace boost { namespace python { +template class class_; + class BOOST_PYTHON_DECL module_base { public: @@ -23,18 +25,12 @@ class BOOST_PYTHON_DECL module_base ~module_base(); // Add elements to the module - void add(PyObject* x, const char* name); - void add(PyTypeObject* x, const char* name = 0); - void add(ref const& x, const char*name); - - // Return true iff a module is currently being built. - static bool initializing(); + void setattr(const char* name, PyObject*); + void setattr(const char* name, ref const&); + void add(PyTypeObject* x); // just use the type's name + void add_type(ref); - // Return the name of the module currently being built. - // REQUIRES: initializing() == true - static string name(); - - // Return a pointer to the Python module object being built + // Return a reference to the Python module object being built ref module() const; private: @@ -48,17 +44,34 @@ class module : public module_base module(const char* name) : module_base(name) {} + // Add elements to the module + module& setattr(const char* name, PyObject*); + module& setattr(const char* name, PyTypeObject*); + module& setattr(const char* name, ref const&); + module& add(PyTypeObject* x); // just use the type's name + + template + module& add(class_ const& c) + { + std::cout << "adding " << typeid(T).name() << " to module" << std::endl << std::flush; + Py_INCREF(c.object()); + this->add_type(c.object()); + return *this; + } + # if 0 template - void def_raw(Fn fn, const char* name) + void def_raw(char const* name, Fn fn) { add(detail::new_raw_arguments_function(fn), name); } -# endif +# endif + template - void def(Fn fn, const char* name) + module& def(char const* name, Fn fn) { - this->add(boost::python::make_function(fn), name); + this->setattr(name, boost::python::make_function(fn)); + return *this; } }; @@ -70,6 +83,30 @@ inline ref module_base::module() const return m_module; } +inline module& module::setattr(const char* name, PyObject* x) +{ + this->module_base::setattr(name, x); + return *this; +} + +inline module& module::setattr(const char* name, PyTypeObject* x) +{ + this->module_base::setattr(name, (PyObject*)x); + return *this; +} + +inline module& module::setattr(const char* name, ref const& x) +{ + this->module_base::setattr(name, x); + return *this; +} + +inline module& module::add(PyTypeObject* x) +{ + this->module_base::add(x); + return *this; +} + }} // namespace boost::python #endif // MODULE_DWA20011221_HPP diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp index 4817e15d..53d886fa 100644 --- a/include/boost/python/object/class.hpp +++ b/include/boost/python/object/class.hpp @@ -30,8 +30,7 @@ struct BOOST_PYTHON_DECL class_base : noncopyable { // constructor class_base( - module& name_space // Which name space the class will live in - , char const* name // The name of the class + char const* name // The name of the class , std::size_t num_types // A list of class_ids. The first is the type , class_id const*const types // this is wrapping. The rest are the types of diff --git a/src/module.cpp b/src/module.cpp index 917f8d3a..dbc81729 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -10,53 +10,38 @@ namespace boost { namespace python { -namespace { - ref name_holder; -} - -bool module_base::initializing() -{ - return name_holder.get() != 0; -} - -string module_base::name() -{ - // If this fails, you haven't created a module object - assert(initializing()); - return string(name_holder); -} - module_base::module_base(const char* name) : m_module( Py_InitModule(const_cast(name), initial_methods) , ref::increment_count) { - // If this fails, you've created more than 1 module object in your module - assert(name_holder.get() == 0); - name_holder = ref(PyObject_GetAttrString( - m_module.get() , const_cast("__name__"))); } module_base::~module_base() { - name_holder.reset(); } -void module_base::add(PyObject* x, const char* name) +void module_base::setattr(const char* name, PyObject* x) { - add(ref(x), name); + setattr(name, ref(x)); } -void module_base::add(ref const& x, const char* name) +void module_base::setattr(char const* name, ref const& x) { // Use function::add_to_namespace to achieve overloading if // appropriate. objects::function::add_to_namespace(m_module, name, x); } -void module_base::add(PyTypeObject* x, const char* name /*= 0*/) +void module_base::add(PyTypeObject* x) { - this->add((PyObject*)x, name ? name : x->tp_name); + this->setattr(x->tp_name, (PyObject*)x); +} + +void module_base::add_type(ref x) +{ + assert(PyObject_TypeCheck(x.get(), &PyType_Type)); + add((PyTypeObject*)x.release()); } PyMethodDef module_base::initial_methods[] = { { 0, 0, 0, 0 } }; diff --git a/src/object/class.cpp b/src/object/class.cpp index 5ebabba1..b928ba66 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -190,11 +189,11 @@ namespace std::vector::const_iterator p = boost::detail::lower_bound(start, finish, id); - + if (p == finish && p->key != id) { string report("extension class wrapper for base class "); - (report += id.name()) += "has not been created yet"; + (report += id.name()) += " has not been created yet"; PyErr_SetObject(PyExc_RuntimeError, report.get()); throw error_already_set(); } @@ -212,7 +211,7 @@ namespace } class_base::class_base( - module& m, char const* name, std::size_t num_types, class_id const* const types) + char const* name, std::size_t num_types, class_id const* const types) { class_registry& r = registry(); assert(num_types >= 1); @@ -234,7 +233,6 @@ class_base::class_base( m_object = ref(PyObject_CallObject(class_metatype().get(), args.get())); r.set(types[0], m_object); - m.add(m_object, name); } }}} // namespace boost::python::objects