diff --git a/base_object.h b/base_object.h index 231dead1..d266bd34 100644 --- a/base_object.h +++ b/base_object.h @@ -14,7 +14,7 @@ # include "wrap_python.h" # include -namespace py { +namespace py { namespace detail { // BaseObject - adds a constructor and non-virtual destructor to a // base Python type (e.g. PyObject, PyTypeObject). @@ -57,6 +57,6 @@ inline BaseObject::~BaseObject() Py_DECREF(ob_type); } -} +}} // namespace py::detail #endif // BASE_OBJECT_DWA051600_H_ diff --git a/caller.h b/caller.h index 7a2e74ca..71100e26 100644 --- a/caller.h +++ b/caller.h @@ -262,7 +262,7 @@ struct Caller return 0; T& target = from_python(self, Type()); (target.*pmf)(); - return none(); + return detail::none(); } template @@ -273,7 +273,7 @@ struct Caller return 0; T& target = from_python(self, Type()); (target.*pmf)(from_python(a1, Type())); - return none(); + return detail::none(); } template @@ -286,7 +286,7 @@ struct Caller T& target = from_python(self, Type()); (target.*pmf)(from_python(a1, Type()), from_python(a2, Type())); - return none(); + return detail::none(); } template @@ -301,7 +301,7 @@ struct Caller (target.*pmf)(from_python(a1, Type()), from_python(a2, Type()), from_python(a3, Type())); - return none(); + return detail::none(); } template @@ -318,7 +318,7 @@ struct Caller from_python(a2, Type()), from_python(a3, Type()), from_python(a4, Type())); - return none(); + return detail::none(); } template @@ -337,7 +337,7 @@ struct Caller from_python(a3, Type()), from_python(a4, Type()), from_python(a5, Type())); - return none(); + return detail::none(); } @@ -348,7 +348,7 @@ struct Caller return 0; T& target = from_python(self, Type()); (target.*pmf)(); - return none(); + return detail::none(); } template @@ -359,7 +359,7 @@ struct Caller return 0; T& target = from_python(self, Type()); (target.*pmf)(from_python(a1, Type())); - return none(); + return detail::none(); } template @@ -372,7 +372,7 @@ struct Caller T& target = from_python(self, Type()); (target.*pmf)(from_python(a1, Type()), from_python(a2, Type())); - return none(); + return detail::none(); } template @@ -387,7 +387,7 @@ struct Caller (target.*pmf)(from_python(a1, Type()), from_python(a2, Type()), from_python(a3, Type())); - return none(); + return detail::none(); } template @@ -404,7 +404,7 @@ struct Caller from_python(a2, Type()), from_python(a3, Type()), from_python(a4, Type())); - return none(); + return detail::none(); } template @@ -423,7 +423,7 @@ struct Caller from_python(a3, Type()), from_python(a4, Type()), from_python(a5, Type())); - return none(); + return detail::none(); } @@ -432,7 +432,7 @@ struct Caller if (!PyArg_ParseTuple(args, const_cast(""))) return 0; f(); - return none(); + return detail::none(); } template @@ -441,7 +441,7 @@ struct Caller if (!PyArg_ParseTuple(args, const_cast("O"), &a1)) return 0; f(from_python(a1, Type())); - return none(); + return detail::none(); } template @@ -452,7 +452,7 @@ struct Caller return 0; f(from_python(a1, Type()), from_python(a2, Type())); - return none(); + return detail::none(); } template @@ -465,7 +465,7 @@ struct Caller f(from_python(a1, Type()), from_python(a2, Type()), from_python(a3, Type())); - return none(); + return detail::none(); } template @@ -480,7 +480,7 @@ struct Caller from_python(a2, Type()), from_python(a3, Type()), from_python(a4, Type())); - return none(); + return detail::none(); } template @@ -497,7 +497,7 @@ struct Caller from_python(a3, Type()), from_python(a4, Type()), from_python(a5, Type())); - return none(); + return detail::none(); } }; diff --git a/cast.h b/cast.h index d9f1bd16..93e95215 100644 --- a/cast.h +++ b/cast.h @@ -14,33 +14,35 @@ namespace py { -// The default way of converting a PyObject* or PyTypeObject* to a T* -template -struct DowncastTraits -{ - template - static T* cast(U* p) { return static_cast(p); } -}; +namespace detail { + // The default way of converting a PyObject* or PyTypeObject* to a T* + template + struct DowncastTraits + { + template + static T* cast(U* p) { return static_cast(p); } + }; -inline PyTypeObject* as_base_object(const PyTypeObject*, PyObject* p) -{ - return reinterpret_cast(p); -} + inline PyTypeObject* as_base_object(const PyTypeObject*, PyObject* p) + { + return reinterpret_cast(p); + } -inline PyObject* as_base_object(const PyObject*, PyObject* p) -{ - return p; -} + inline PyObject* as_base_object(const PyObject*, PyObject* p) + { + return p; + } -inline const PyTypeObject* as_base_object(const PyTypeObject*, const PyObject* p) -{ - return reinterpret_cast(p); -} + inline const PyTypeObject* as_base_object(const PyTypeObject*, const PyObject* p) + { + return reinterpret_cast(p); + } -inline const PyObject* as_base_object(const PyObject*, const PyObject* p) -{ - return p; -} + inline const PyObject* as_base_object(const PyObject*, const PyObject* p) + { + return p; + } +} // namespace detail // Convert a pointer to any type derived from PyObject or PyTypeObject to a PyObject* inline PyObject* as_object(PyObject* p) { return p; } @@ -52,28 +54,28 @@ template struct Downcast : boost::dereferenceable, T*> { Downcast(PyObject* p) - : m_p(DowncastTraits::cast(as_base_object((T*)0, p))) + : m_p(detail::DowncastTraits::cast(detail::as_base_object((T*)0, p))) {} Downcast(const PyObject* p) - : m_p(DowncastTraits::cast(as_base_object((const T*)0, p))) + : m_p(detail::DowncastTraits::cast(detail::as_base_object((const T*)0, p))) {} Downcast(PyTypeObject* p) - : m_p(DowncastTraits::cast(p)) + : m_p(detail::DowncastTraits::cast(p)) {} Downcast(const PyTypeObject* p) - : m_p(DowncastTraits::cast(p)) + : m_p(detail::DowncastTraits::cast(p)) {} operator T*() const { return m_p; } T* get() const { return m_p; } T& operator*() const { return *m_p; } -private: + private: T* m_p; }; -} +} // namespace py #endif // CAST_DWA052500_H_ diff --git a/class_wrapper.h b/class_wrapper.h index 433ce46c..85e2de79 100644 --- a/class_wrapper.h +++ b/class_wrapper.h @@ -11,13 +11,13 @@ namespace py { // Syntactic sugar to make wrapping classes more convenient -template > +template > class ClassWrapper : PyExtensionClassConverters // Works around MSVC6.x/GCC2.95.2 bug described below { public: ClassWrapper(Module& module, const char* name) - : m_class(new ExtensionClass(name)) + : m_class(new detail::ExtensionClass(name)) { module.add(Ptr(as_object(m_class.get()), Ptr::new_ref), name); } @@ -108,24 +108,8 @@ class ClassWrapper m_class->declare_base(base.get_extension_class(), without_downcast); } - // declare the given class a base class of this one and register - // conversion functions - template - void declare_base(ExtensionClass * base) - { - m_class->declare_base(base); - } - - // declare the given class a base class of this one and register - // upcast conversion function - template - void declare_base(ExtensionClass * base, WithoutDowncast) - { - m_class->declare_base(base, without_downcast); - } - // get the embedded ExtensioClass object - ExtensionClass * get_extension_class() const + detail::ExtensionClass * get_extension_class() const { return m_class.get(); } @@ -137,7 +121,23 @@ class ClassWrapper void add(Ptr x, const char* name) { m_class->set_attribute(name, x); } private: - PyPtr > m_class; + // declare the given class a base class of this one and register + // conversion functions + template + void declare_base(detail::ExtensionClass * base) + { + m_class->declare_base(base); + } + + // declare the given class a base class of this one and register + // upcast conversion function + template + void declare_base(detail::ExtensionClass * base, WithoutDowncast) + { + m_class->declare_base(base, without_downcast); + } + + PyPtr > m_class; }; // The bug mentioned at the top of this file is that on certain compilers static diff --git a/extclass.cpp b/extclass.cpp index 9566d6f8..b76853b6 100644 --- a/extclass.cpp +++ b/extclass.cpp @@ -132,7 +132,6 @@ namespace detail { return 2; } } -} // namespace detail ExtensionInstance* get_extension_instance(PyObject* p) { @@ -448,9 +447,6 @@ void ExtensionClassBase::set_attribute(const char* name, Ptr x) detail::enable_named_method(this, name); } -namespace detail -{ - operator_dispatcher::operator_dispatcher(const Ptr& o, const Ptr& s) : m_object(o), m_self(s), m_free_list_link(0) diff --git a/extclass.h b/extclass.h index a123cb95..55d83e21 100644 --- a/extclass.h +++ b/extclass.h @@ -25,12 +25,26 @@ namespace py { +// forward declarations +template struct operators; +template struct left_operand; +template struct right_operand; + +enum WithoutDowncast { without_downcast }; + +namespace detail { + // forward declarations class ExtensionInstance; class ExtensionClassBase; template class InstanceHolder; template class InstanceValueHolder; template class InstancePtrHolder; +template struct operand_select; + template struct choose_op; + template struct choose_rop; + template struct choose_unary_op; + template struct define_operator; MetaClass* extension_meta_class(); ExtensionInstance* get_extension_instance(PyObject* p); @@ -49,23 +63,21 @@ T* check_non_null(T* p) template class HeldInstance; -namespace detail { - typedef void* (*ConversionFunction)(void*); +typedef void* (*ConversionFunction)(void*); - struct BaseClassInfo - { - BaseClassInfo(ExtensionClassBase* t, ConversionFunction f) - :class_object(t), convert(f) - {} +struct BaseClassInfo +{ + BaseClassInfo(ExtensionClassBase* t, ConversionFunction f) + :class_object(t), convert(f) + {} - ExtensionClassBase* class_object; - ConversionFunction convert; - }; + ExtensionClassBase* class_object; + ConversionFunction convert; +}; - typedef BaseClassInfo DerivedClassInfo; +typedef BaseClassInfo DerivedClassInfo; - struct add_operator_base; -} +struct add_operator_base; class ExtensionClassBase : public Class { @@ -84,11 +96,11 @@ class ExtensionClassBase : public Class private: virtual void* extract_object_from_holder(InstanceHolderBase* v) const = 0; - virtual std::vector const& base_classes() const = 0; - virtual std::vector const& derived_classes() const = 0; + virtual std::vector const& base_classes() const = 0; + virtual std::vector const& derived_classes() const = 0; protected: - friend struct detail::add_operator_base; + friend struct add_operator_base; void add_method(PyPtr method, const char* name); void add_method(Function* method, const char* name); @@ -109,19 +121,19 @@ class ClassRegistry static void unregister_class(ExtensionClassBase*); // Establish C++ inheritance relationships - static void register_base_class(py::detail::BaseClassInfo const&); - static void register_derived_class(py::detail::DerivedClassInfo const&); + static void register_base_class(BaseClassInfo const&); + static void register_derived_class(DerivedClassInfo const&); // Query the C++ inheritance relationships - static std::vector const& base_classes(); - static std::vector const& derived_classes(); + static std::vector const& base_classes(); + static std::vector const& derived_classes(); private: static ExtensionClassBase* static_class_object; - static std::vector static_base_class_info; - static std::vector static_derived_class_info; + static std::vector static_base_class_info; + static std::vector static_derived_class_info; }; -} +}} // namespace py::detail PY_BEGIN_CONVERSION_NAMESPACE @@ -129,7 +141,7 @@ PY_BEGIN_CONVERSION_NAMESPACE // and U. T is the class the user really intends to wrap. U is a class derived // from T with some virtual function overriding boilerplate, or if there are no // virtual functions, U = HeldInstance. -template > +template > class PyExtensionClassConverters { public: @@ -160,10 +172,10 @@ class PyExtensionClassConverters // writes code which causes us to try to copy a T. PyObject* to_python(const T& x) const { - py::PyPtr result(create_instance()); + py::PyPtr result(create_instance()); result->add_implementation( - std::auto_ptr( - new py::InstanceValueHolder(result.get(), x))); + std::auto_ptr( + new py::detail::InstanceValueHolder(result.get(), x))); return result.release(); } @@ -171,21 +183,21 @@ class PyExtensionClassConverters friend T* from_python(PyObject* obj, py::Type) { // Downcast to an ExtensionInstance, then find the actual T - py::ExtensionInstance* self = py::get_extension_instance(obj); - typedef std::vector::const_iterator Iterator; + py::detail::ExtensionInstance* self = py::detail::get_extension_instance(obj); + typedef std::vector::const_iterator Iterator; for (Iterator p = self->wrapped_objects().begin(); p != self->wrapped_objects().end(); ++p) { - py::InstanceHolder* held = dynamic_cast*>(*p); + py::detail::InstanceHolder* held = dynamic_cast*>(*p); if (held != 0) return held->target(); // see extclass.cpp for an explanation of try_class_conversions() - void* target = py::ClassRegistry::class_object()->try_class_conversions(*p); + void* target = py::detail::ClassRegistry::class_object()->try_class_conversions(*p); if(target) return static_cast(target); } - py::report_missing_instance_data(self, py::ClassRegistry::class_object(), typeid(T)); + py::detail::report_missing_instance_data(self, py::detail::ClassRegistry::class_object(), typeid(T)); throw py::ArgumentError(); } @@ -194,38 +206,38 @@ class PyExtensionClassConverters static PtrType& ptr_from_python(PyObject* obj, py::Type) { // Downcast to an ExtensionInstance, then find the actual T - py::ExtensionInstance* self = py::get_extension_instance(obj); - typedef std::vector::const_iterator Iterator; + py::detail::ExtensionInstance* self = py::detail::get_extension_instance(obj); + typedef std::vector::const_iterator Iterator; for (Iterator p = self->wrapped_objects().begin(); p != self->wrapped_objects().end(); ++p) { - py::InstancePtrHolder* held = - dynamic_cast*>(*p); + py::detail::InstancePtrHolder* held = + dynamic_cast*>(*p); if (held != 0) return held->ptr(); } - py::report_missing_ptr_data(self, py::ClassRegistry::class_object(), typeid(T)); + py::detail::report_missing_ptr_data(self, py::detail::ClassRegistry::class_object(), typeid(T)); throw py::ArgumentError(); } template static PyObject* ptr_to_python(PtrType x) { - py::PyPtr result(create_instance()); + py::PyPtr result(create_instance()); result->add_implementation( - std::auto_ptr( - new py::InstancePtrHolder(x))); + std::auto_ptr( + new py::detail::InstancePtrHolder(x))); return result.release(); } - static py::PyPtr create_instance() + static py::PyPtr create_instance() { - PyTypeObject* class_object = py::ClassRegistry::class_object(); + PyTypeObject* class_object = py::detail::ClassRegistry::class_object(); if (class_object == 0) - py::report_missing_class_object(typeid(T)); + py::detail::report_missing_class_object(typeid(T)); - return py::PyPtr( - new py::ExtensionInstance(class_object)); + return py::PyPtr( + new py::detail::ExtensionInstance(class_object)); } // Convert to const T* @@ -242,7 +254,7 @@ class PyExtensionClassConverters // Convert to T& friend T& from_python(PyObject* p, py::Type) - { return *py::check_non_null(from_python(p, py::Type())); } + { return *py::detail::check_non_null(from_python(p, py::Type())); } // Convert to const T& friend const T& from_python(PyObject* p, py::Type) @@ -293,6 +305,8 @@ namespace py { PY_IMPORT_CONVERSION(PyExtensionClassConverters); +namespace detail { + template class InstanceHolder; class ReadOnlySetattrFunction : public Function @@ -305,72 +319,6 @@ class ReadOnlySetattrFunction : public Function String m_name; }; -enum operator_id -{ - op_add = 0x1, - op_sub = 0x2, - op_mul = 0x4, - op_div = 0x8, - op_mod = 0x10, - op_divmod =0x20, - op_pow = 0x40, - op_lshift = 0x80, - op_rshift = 0x100, - op_and = 0x200, - op_xor = 0x400, - op_or = 0x800, - op_neg = 0x1000, - op_pos = 0x2000, - op_abs = 0x4000, - op_invert = 0x8000, - op_int = 0x10000, - op_long = 0x20000, - op_float = 0x40000, - op_str = 0x80000, - op_cmp = 0x100000 -}; - -namespace detail -{ - struct auto_operand {}; - - template - struct operand_select - { - template - struct wrapped - { - typedef Specified type; - }; - }; - - template <> - struct operand_select - { - template - struct wrapped - { - typedef const WrappedType& type; - }; - }; - - template struct define_operator; - template struct choose_op; - template struct choose_rop; - template struct choose_unary_op; -} - -template -struct operators {}; - -template -struct left_operand {}; - -template -struct right_operand {}; - -namespace detail -{ template struct DefineConversion { @@ -384,9 +332,6 @@ namespace detail return dynamic_cast(static_cast(v)); } }; -} - -enum WithoutDowncast { without_downcast }; // An easy way to make an extension base class which wraps T. Note that Python // subclasses of this class will simply be Class objects. @@ -439,7 +384,7 @@ class ExtensionClass template inline void def(operators) { - typedef typename detail::operand_select::template wrapped::type true_operand; + typedef typename operand_select::template wrapped::type true_operand; def_operators(operators()); } @@ -453,7 +398,7 @@ class ExtensionClass template inline void def(operators, right_operand r) { - typedef typename detail::operand_select::template wrapped::type true_left; + typedef typename operand_select::template wrapped::type true_left; def_operators(operators(), r); } @@ -469,7 +414,7 @@ class ExtensionClass template inline void def(operators, left_operand l) { - typedef typename detail::operand_select::template wrapped::type true_right; + typedef typename operand_select::template wrapped::type true_right; def_operators(operators(), l); } @@ -482,7 +427,7 @@ class ExtensionClass template inline void def_raw(Fn fn, const char* name) { - this->add_method(py::detail::new_raw_arguments_function(fn), name); + this->add_method(new_raw_arguments_function(fn), name); } // define member functions. In fact this works for free functions, too - @@ -501,7 +446,7 @@ class ExtensionClass template inline void def(Fn fn, const char* name, DefaultFn default_fn) { - this->add_method(py::detail::new_virtual_function(Type(), fn, default_fn), name); + this->add_method(new_virtual_function(Type(), fn, default_fn), name); } // Provide a function which implements x., reading from the given @@ -543,13 +488,13 @@ class ExtensionClass { // see extclass.cpp for an explanation of why we need to register // conversion functions - detail::BaseClassInfo baseInfo(base, - &detail::DefineConversion::downcast_ptr); + BaseClassInfo baseInfo(base, + &DefineConversion::downcast_ptr); ClassRegistry::register_base_class(baseInfo); add_base(Ptr(as_object(base), Ptr::new_ref)); - detail::DerivedClassInfo derivedInfo(this, - &detail::DefineConversion::upcast_ptr); + DerivedClassInfo derivedInfo(this, + &DefineConversion::upcast_ptr); ClassRegistry::register_derived_class(derivedInfo); } @@ -560,12 +505,12 @@ class ExtensionClass { // see extclass.cpp for an explanation of why we need to register // conversion functions - detail::BaseClassInfo baseInfo(base, 0); + BaseClassInfo baseInfo(base, 0); ClassRegistry::register_base_class(baseInfo); add_base(Ptr(as_object(base), Ptr::new_ref)); - detail::DerivedClassInfo derivedInfo(this, - &detail::DefineConversion::upcast_ptr); + DerivedClassInfo derivedInfo(this, + &DefineConversion::upcast_ptr); ClassRegistry::register_derived_class(derivedInfo); } @@ -573,8 +518,8 @@ class ExtensionClass typedef InstanceValueHolder Holder; private: // ExtensionClassBase virtual function implementations - std::vector const& base_classes() const; - std::vector const& derived_classes() const; + std::vector const& base_classes() const; + std::vector const& derived_classes() const; void* extract_object_from_holder(InstanceHolderBase* v) const; private: // Utility functions @@ -582,28 +527,32 @@ class ExtensionClass inline void def_operators(operators) { register_coerce(); - - detail::choose_op<(which & op_add)>::template args::add(this); - detail::choose_op<(which & op_sub)>::template args::add(this); - detail::choose_op<(which & op_mul)>::template args::add(this); - detail::choose_op<(which & op_div)>::template args::add(this); - detail::choose_op<(which & op_mod)>::template args::add(this); - detail::choose_op<(which & op_divmod)>::template args::add(this); - detail::choose_op<(which & op_pow)>::template args::add(this); - detail::choose_op<(which & op_lshift)>::template args::add(this); - detail::choose_op<(which & op_rshift)>::template args::add(this); - detail::choose_op<(which & op_and)>::template args::add(this); - detail::choose_op<(which & op_xor)>::template args::add(this); - detail::choose_op<(which & op_or)>::template args::add(this); - detail::choose_unary_op<(which & op_neg)>::template args::add(this); - detail::choose_unary_op<(which & op_pos)>::template args::add(this); - detail::choose_unary_op<(which & op_abs)>::template args::add(this); - detail::choose_unary_op<(which & op_invert)>::template args::add(this); - detail::choose_unary_op<(which & op_int)>::template args::add(this); - detail::choose_unary_op<(which & op_long)>::template args::add(this); - detail::choose_unary_op<(which & op_float)>::template args::add(this); - detail::choose_op<(which & op_cmp)>::template args::add(this); - detail::choose_unary_op<(which & op_str)>::template args::add(this); + + // for some strange reason, this prevents MSVC from having an + // "unrecoverable block scoping error"! + typedef choose_op<(which & op_add)> choose_add; + + choose_op<(which & op_add)>::template args::add(this); + choose_op<(which & op_sub)>::template args::add(this); + choose_op<(which & op_mul)>::template args::add(this); + choose_op<(which & op_div)>::template args::add(this); + choose_op<(which & op_mod)>::template args::add(this); + choose_op<(which & op_divmod)>::template args::add(this); + choose_op<(which & op_pow)>::template args::add(this); + choose_op<(which & op_lshift)>::template args::add(this); + choose_op<(which & op_rshift)>::template args::add(this); + choose_op<(which & op_and)>::template args::add(this); + choose_op<(which & op_xor)>::template args::add(this); + choose_op<(which & op_or)>::template args::add(this); + choose_unary_op<(which & op_neg)>::template args::add(this); + choose_unary_op<(which & op_pos)>::template args::add(this); + choose_unary_op<(which & op_abs)>::template args::add(this); + choose_unary_op<(which & op_invert)>::template args::add(this); + choose_unary_op<(which & op_int)>::template args::add(this); + choose_unary_op<(which & op_long)>::template args::add(this); + choose_unary_op<(which & op_float)>::template args::add(this); + choose_op<(which & op_cmp)>::template args::add(this); + choose_unary_op<(which & op_str)>::template args::add(this); } template @@ -611,19 +560,19 @@ class ExtensionClass { register_coerce(); - detail::choose_op<(which & op_add)>::template args::add(this); - detail::choose_op<(which & op_sub)>::template args::add(this); - detail::choose_op<(which & op_mul)>::template args::add(this); - detail::choose_op<(which & op_div)>::template args::add(this); - detail::choose_op<(which & op_mod)>::template args::add(this); - detail::choose_op<(which & op_divmod)>::template args::add(this); - detail::choose_op<(which & op_pow)>::template args::add(this); - detail::choose_op<(which & op_lshift)>::template args::add(this); - detail::choose_op<(which & op_rshift)>::template args::add(this); - detail::choose_op<(which & op_and)>::template args::add(this); - detail::choose_op<(which & op_xor)>::template args::add(this); - detail::choose_op<(which & op_or)>::template args::add(this); - detail::choose_op<(which & op_cmp)>::template args::add(this); + choose_op<(which & op_add)>::template args::add(this); + choose_op<(which & op_sub)>::template args::add(this); + choose_op<(which & op_mul)>::template args::add(this); + choose_op<(which & op_div)>::template args::add(this); + choose_op<(which & op_mod)>::template args::add(this); + choose_op<(which & op_divmod)>::template args::add(this); + choose_op<(which & op_pow)>::template args::add(this); + choose_op<(which & op_lshift)>::template args::add(this); + choose_op<(which & op_rshift)>::template args::add(this); + choose_op<(which & op_and)>::template args::add(this); + choose_op<(which & op_xor)>::template args::add(this); + choose_op<(which & op_or)>::template args::add(this); + choose_op<(which & op_cmp)>::template args::add(this); } template @@ -631,19 +580,19 @@ class ExtensionClass { register_coerce(); - detail::choose_rop<(which & op_add)>::template args::add(this); - detail::choose_rop<(which & op_sub)>::template args::add(this); - detail::choose_rop<(which & op_mul)>::template args::add(this); - detail::choose_rop<(which & op_div)>::template args::add(this); - detail::choose_rop<(which & op_mod)>::template args::add(this); - detail::choose_rop<(which & op_divmod)>::template args::add(this); - detail::choose_rop<(which & op_pow)>::template args::add(this); - detail::choose_rop<(which & op_lshift)>::template args::add(this); - detail::choose_rop<(which & op_rshift)>::template args::add(this); - detail::choose_rop<(which & op_and)>::template args::add(this); - detail::choose_rop<(which & op_xor)>::template args::add(this); - detail::choose_rop<(which & op_or)>::template args::add(this); - detail::choose_rop<(which & op_cmp)>::template args::add(this); + choose_rop<(which & op_add)>::template args::add(this); + choose_rop<(which & op_sub)>::template args::add(this); + choose_rop<(which & op_mul)>::template args::add(this); + choose_rop<(which & op_div)>::template args::add(this); + choose_rop<(which & op_mod)>::template args::add(this); + choose_rop<(which & op_divmod)>::template args::add(this); + choose_rop<(which & op_pow)>::template args::add(this); + choose_rop<(which & op_lshift)>::template args::add(this); + choose_rop<(which & op_rshift)>::template args::add(this); + choose_rop<(which & op_and)>::template args::add(this); + choose_rop<(which & op_xor)>::template args::add(this); + choose_rop<(which & op_or)>::template args::add(this); + choose_rop<(which & op_cmp)>::template args::add(this); } template @@ -770,10 +719,7 @@ class ExtensionInstance : public Instance // Template function implementations // -namespace detail -{ - Tuple extension_class_coerce(Ptr l, Ptr r); -} +Tuple extension_class_coerce(Ptr l, Ptr r); template ExtensionClass::ExtensionClass() @@ -795,12 +741,12 @@ void ExtensionClass::register_coerce() Ptr coerce_fct = dict().get_item(String("__coerce__")); if(coerce_fct.get() == 0) // not yet defined - this->def(&py::detail::extension_class_coerce, "__coerce__"); + this->def(&extension_class_coerce, "__coerce__"); } template inline -std::vector const& +std::vector const& ExtensionClass::base_classes() const { return ClassRegistry::base_classes(); @@ -808,7 +754,7 @@ ExtensionClass::base_classes() const template inline -std::vector const& +std::vector const& ExtensionClass::derived_classes() const { return ClassRegistry::derived_classes(); @@ -817,7 +763,7 @@ ExtensionClass::derived_classes() const template void* ExtensionClass::extract_object_from_holder(InstanceHolderBase* v) const { - py::InstanceHolder* held = dynamic_cast*>(v); + InstanceHolder* held = dynamic_cast*>(v); if(held) return held->target(); return 0; @@ -847,25 +793,25 @@ inline void ClassRegistry::unregister_class(ExtensionClassBase* p) } template -void ClassRegistry::register_base_class(py::detail::BaseClassInfo const& i) +void ClassRegistry::register_base_class(BaseClassInfo const& i) { static_base_class_info.push_back(i); } template -void ClassRegistry::register_derived_class(py::detail::DerivedClassInfo const& i) +void ClassRegistry::register_derived_class(DerivedClassInfo const& i) { static_derived_class_info.push_back(i); } template -std::vector const& ClassRegistry::base_classes() +std::vector const& ClassRegistry::base_classes() { return static_base_class_info; } template -std::vector const& ClassRegistry::derived_classes() +std::vector const& ClassRegistry::derived_classes() { return static_derived_class_info; } @@ -876,11 +822,11 @@ std::vector const& ClassRegistry::derived_class template ExtensionClassBase* ClassRegistry::static_class_object; template -std::vector ClassRegistry::static_base_class_info; +std::vector ClassRegistry::static_base_class_info; template -std::vector ClassRegistry::static_derived_class_info; +std::vector ClassRegistry::static_derived_class_info; -} // namespace py +}} // namespace py::detail #endif // EXTENSION_CLASS_DWA052000_H_ diff --git a/extclass_demo.cpp b/extclass_demo.cpp index 7f690277..68716e06 100644 --- a/extclass_demo.cpp +++ b/extclass_demo.cpp @@ -44,15 +44,8 @@ std::string FooCallback::pure() const return py::Callback::call_method(m_self, "pure"); } -// The initializer for ExtensionClass is entirely optional. It -// only affects the way that instances of this class _print_ in Python. If you -// need an absolutely predictable name for the type, use the -// initializer. Otherwise, C++ will generate an implementation-dependent -// representation of the type name, usually something like "class -// extclass_demo::Foo". I've supplied it here in part so that I can write -// doctests that exactly anticipate the generated error messages. -Foo::PythonClass::PythonClass() - : py::ExtensionClass("Foo") // optional +Foo::PythonClass::PythonClass(py::Module& m) + : py::ClassWrapper(m, "Foo") { def(py::Constructor()); def(&Foo::mumble, "mumble"); @@ -66,8 +59,8 @@ Foo::PythonClass::PythonClass() // Since pure() is pure virtual, we are leaving it undefined. } -BarPythonClass::BarPythonClass() - : py::ExtensionClass("Bar") // optional +BarPythonClass::BarPythonClass(py::Module& m) + : py::ClassWrapper(m, "Bar") { def(py::Constructor()); def(&Bar::first, "first"); @@ -75,10 +68,10 @@ BarPythonClass::BarPythonClass() def(&Bar::pass_baz, "pass_baz"); } -BazPythonClass::BazPythonClass() - : py::ExtensionClass("Baz") // optional +BazPythonClass::BazPythonClass(py::Module& m) + : py::ClassWrapper(m, "Baz") // optional { - def(py::Constructor()); + def(py::Constructor<>()); def(&Baz::pass_bar, "pass_bar"); def(&Baz::clone, "clone"); def(&Baz::create_foo, "create_foo"); @@ -86,10 +79,10 @@ BazPythonClass::BazPythonClass() def(&Baz::eat_baz, "eat_baz"); } -StringMapPythonClass::StringMapPythonClass() - : py::ExtensionClass("StringMap") +StringMapPythonClass::StringMapPythonClass(py::Module& m) + : py::ClassWrapper(m, "StringMap") { - def(py::Constructor()); + def(py::Constructor<>()); def(&StringMap::size, "__len__"); def(&get_item, "__getitem__"); def(&set_item, "__setitem__"); @@ -112,8 +105,8 @@ void del_first(const IntPair&) throw py::ErrorAlreadySet(); } -IntPairPythonClass::IntPairPythonClass() - : py::ExtensionClass("IntPair") +IntPairPythonClass::IntPairPythonClass(py::Module& m) + : py::ClassWrapper(m, "IntPair") { def(py::Constructor()); def(&getattr, "__getattr__"); @@ -721,7 +714,7 @@ const Record* get_record() return &v; } -template class py::ExtensionClass; // explicitly instantiate +template class py::ClassWrapper; // explicitly instantiate } // namespace extclass_demo @@ -841,14 +834,14 @@ void init_module(py::Module& m) py::ClassWrapper fubar(m, "Fubar"); fubar.def(py::Constructor()); fubar.def(py::Constructor()); - - m.add(new Foo::PythonClass); - m.add(new BarPythonClass); - m.add(new BazPythonClass); - m.add(new StringMapPythonClass); - m.add(new IntPairPythonClass); + + Foo::PythonClass foo(m); + BarPythonClass bar(m); + BazPythonClass baz(m); + StringMapPythonClass string_map(m); + IntPairPythonClass int_pair(m); m.def(make_pair, "make_pair"); - m.add(new CompareIntPairPythonClass); + CompareIntPairPythonClass compare_int_pair(m); py::ClassWrapper string_pair(m, "StringPair"); string_pair.def(py::Constructor()); @@ -896,7 +889,7 @@ void init_module(py::Module& m) m.def(&test5, "overloaded"); py::ClassWrapper over(m, "OverloadTest"); - over.def(py::Constructor()); + over.def(py::Constructor<>()); over.def(py::Constructor()); over.def(py::Constructor()); over.def(py::Constructor()); @@ -937,7 +930,7 @@ void init_module(py::Module& m) m.def(&testCallback, "testCallback"); py::ClassWrapper callbackTest(m, "CallbackTest"); - callbackTest.def(py::Constructor()); + callbackTest.def(py::Constructor<>()); callbackTest.def(&CallbackTest::callback, "callback", &CallbackTestCallback::default_callback); callbackTest.def(&CallbackTest::callbackString, "callback", @@ -1083,10 +1076,10 @@ void initdemo() } // Need a way to report other errors here } -CompareIntPairPythonClass::CompareIntPairPythonClass() - : py::ExtensionClass("CompareIntPair") +CompareIntPairPythonClass::CompareIntPairPythonClass(py::Module& m) + : py::ClassWrapper(m, "CompareIntPair") { - def(py::Constructor()); + def(py::Constructor<>()); def(&CompareIntPair::operator(), "__call__"); } diff --git a/extclass_demo.h b/extclass_demo.h index 04e3f9e3..c9938c92 100644 --- a/extclass_demo.h +++ b/extclass_demo.h @@ -12,7 +12,7 @@ // Example code demonstrating extension class usage // -# include "extclass.h" +# include "class_wrapper.h" # include "callback.h" # include # include @@ -184,21 +184,21 @@ class FooCallback : public Foo }; // Define the Python base class -struct Foo::PythonClass : py::ExtensionClass { PythonClass(); }; +struct Foo::PythonClass : py::ClassWrapper { PythonClass(py::Module&); }; // No virtual functions on Bar or Baz which are actually supposed to behave // virtually from C++, so we'll rely on the library to define a wrapper for // us. Even so, Python Class types for each type we're wrapping should be // _defined_ here in a header where they can be seen by other extension class -// definitions, since it is the definition of the py::ExtensionClass<> that +// definitions, since it is the definition of the py::ClassWrapper<> that // causes to_python/from_python conversion functions to be generated. -struct BarPythonClass : py::ExtensionClass { BarPythonClass(); }; -struct BazPythonClass : py::ExtensionClass { BazPythonClass(); }; +struct BarPythonClass : py::ClassWrapper { BarPythonClass(py::Module&); }; +struct BazPythonClass : py::ClassWrapper { BazPythonClass(py::Module&); }; struct StringMapPythonClass - : py::ExtensionClass + : py::ClassWrapper { - StringMapPythonClass(); + StringMapPythonClass(py::Module&); // These static functions implement the right argument protocols for // implementing the Python "special member functions" for mapping on @@ -209,9 +209,9 @@ struct StringMapPythonClass }; struct IntPairPythonClass - : py::ExtensionClass + : py::ClassWrapper { - IntPairPythonClass(); + IntPairPythonClass(py::Module&); // The following could just as well be a free function; it implements the // getattr functionality for IntPair. @@ -221,9 +221,9 @@ struct IntPairPythonClass }; struct CompareIntPairPythonClass - : py::ExtensionClass + : py::ClassWrapper { - CompareIntPairPythonClass(); + CompareIntPairPythonClass(py::Module&); }; } // namespace extclass_demo diff --git a/functions.cpp b/functions.cpp index 4976a2cd..7e07c4d8 100644 --- a/functions.cpp +++ b/functions.cpp @@ -12,10 +12,10 @@ #include "objects.h" #include "errors.h" -namespace py { +namespace py { namespace detail { struct Function::TypeObject : - Singleton > > + Singleton > > { TypeObject() : SingletonBase(&PyType_Type) {} }; @@ -115,7 +115,7 @@ BoundFunction* BoundFunction::create(const Ptr& target, const Ptr& fn) // attribute of built-in Python functions can be accessed when bound. struct BoundFunction::TypeObject : Singleton > > > + Getattrable > > > { TypeObject() : SingletonBase(&PyType_Type) {} @@ -164,4 +164,4 @@ void BoundFunction::TypeObject::dealloc(BoundFunction* instance) const BoundFunction* BoundFunction::free_list; -} +}} // namespace py::detail diff --git a/functions.h b/functions.h index 9f8add61..36c6de13 100644 --- a/functions.h +++ b/functions.h @@ -20,7 +20,7 @@ # include # include -namespace py { +namespace py { namespace detail { // forward declaration class ExtensionInstance; @@ -158,41 +158,39 @@ inline Function* new_wrapped_function(F pmf) return new_wrapped_function_aux(return_value(pmf), pmf); } -namespace detail { - template - Function* new_raw_arguments_function(R (*pmf)(Args, Keywords)) - { - return new raw_arguments_function(pmf); - } +template +Function* new_raw_arguments_function(R (*pmf)(Args, Keywords)) +{ + return new raw_arguments_function(pmf); +} - // A helper function for new_virtual_function(), below. Implements the core - // functionality once the return type has already been deduced. R is expected to - // be Type, where X is the actual return type of V. - template - inline Function* new_virtual_function_aux( - Type, R, V virtual_function_ptr, D default_implementation - ) - { - // We can't just use "typename R::Type" below because MSVC (incorrectly) pukes. - typedef typename R::Type ReturnType; - return new virtual_function( - virtual_function_ptr, default_implementation); - } +// A helper function for new_virtual_function(), below. Implements the core +// functionality once the return type has already been deduced. R is expected to +// be Type, where X is the actual return type of V. +template +inline Function* new_virtual_function_aux( + Type, R, V virtual_function_ptr, D default_implementation + ) +{ + // We can't just use "typename R::Type" below because MSVC (incorrectly) pukes. + typedef typename R::Type ReturnType; + return new virtual_function( + virtual_function_ptr, default_implementation); +} - // Create and return a new virtual_function object wrapping the given - // virtual_function_ptr and default_implementation - template - inline Function* new_virtual_function( - Type, V virtual_function_ptr, D default_implementation - ) - { - // Deduce the return type and pass it off to the helper function above - return new_virtual_function_aux( - Type(), return_value(virtual_function_ptr), - virtual_function_ptr, default_implementation); - } -} // namespace detail +// Create and return a new virtual_function object wrapping the given +// virtual_function_ptr and default_implementation +template +inline Function* new_virtual_function( + Type, V virtual_function_ptr, D default_implementation + ) +{ + // Deduce the return type and pass it off to the helper function above + return new_virtual_function_aux( + Type(), return_value(virtual_function_ptr), + virtual_function_ptr, default_implementation); +} // A function with a bundled "bound target" object. This is what is produced by // the expression a.b where a is an Instance or ExtensionInstance object and b @@ -303,7 +301,6 @@ PyObject* virtual_function::do_call(PyObject* args, PyObject* keywords) return Caller::call(m_default_implementation, args, keywords); } - -} +}} // namespace py::detail #endif // FUNCTIONS_DWA051400_H_ diff --git a/init_function.cpp b/init_function.cpp index 33add6ce..defe7ee3 100644 --- a/init_function.cpp +++ b/init_function.cpp @@ -11,26 +11,26 @@ #include "extclass.h" #include -namespace py { +namespace py { namespace detail { -PyObject* Init::do_call(PyObject* args_, PyObject* keywords) const -{ - Tuple args(Ptr(args_, Ptr::borrowed)); - if (args[0]->ob_type->ob_type != extension_meta_class()) - { - PyErr_SetString(PyExc_TypeError, "argument 1 to __init__ must be an ExtensionInstance"); - return 0; - } - - ExtensionInstance *self = static_cast(args[0].get()); - - Tuple ctor_args = args.slice(1, args.size()); - - std::auto_ptr result( - create_holder(self, ctor_args.get(), keywords)); - - self->add_implementation(result); - return none(); -} + PyObject* Init::do_call(PyObject* args_, PyObject* keywords) const + { + Tuple args(Ptr(args_, Ptr::borrowed)); + if (args[0]->ob_type->ob_type != extension_meta_class()) + { + PyErr_SetString(PyExc_TypeError, "argument 1 to __init__ must be an ExtensionInstance"); + return 0; + } -} + ExtensionInstance *self = static_cast(args[0].get()); + + Tuple ctor_args = args.slice(1, args.size()); + + std::auto_ptr result( + create_holder(self, ctor_args.get(), keywords)); + + self->add_implementation(result); + return none(); + } + +}} // namespace py::detail diff --git a/init_function.h b/init_function.h index 5ee49b26..6facbe68 100644 --- a/init_function.h +++ b/init_function.h @@ -99,7 +99,6 @@ namespace detail { private: const_reference value; }; -} class ExtensionInstance; class InstanceHolderBase; @@ -283,6 +282,6 @@ struct Init5 : Init { return typeid(void (*)(T&, A1, A2, A3, A4, A5)).name(); } }; -} +}} // namespace py::detail #endif // INIT_FUNCTION_DWA052000_H_ diff --git a/module.cpp b/module.cpp index 4605b787..c61fda43 100644 --- a/module.cpp +++ b/module.cpp @@ -26,14 +26,14 @@ Module::Module(const char* name) { // If this fails, you've created more than 1 Module object in your module assert(name_holder.get() == 0); - name_holder = Ptr(PyObject_GetAttrString(m_module, "__name__")); + name_holder = Ptr(PyObject_GetAttrString(m_module, const_cast("__name__"))); } void -Module::add(Function* x, const char* name) +Module::add(detail::Function* x, const char* name) { - PyPtr f(x); // First take possession of the object. - Function::add_to_namespace(f, name, PyModule_GetDict(m_module)); + PyPtr f(x); // First take possession of the object. + detail::Function::add_to_namespace(f, name, PyModule_GetDict(m_module)); } void Module::add(Ptr x, const char* name) diff --git a/module.h b/module.h index 7daee935..64459e3f 100644 --- a/module.h +++ b/module.h @@ -25,20 +25,20 @@ class Module Module(const char* name); // Add elements to the module - void add(Function* x, const char* name); + void add(detail::Function* x, const char* name); void add(PyTypeObject* x, const char* name = 0); void add(Ptr x, const char*name); template void def_raw(Fn fn, const char* name) { - add(py::detail::new_raw_arguments_function(fn), name); + add(detail::new_raw_arguments_function(fn), name); } template void def(Fn fn, const char* name) { - add(new_wrapped_function(fn), name); + add(detail::new_wrapped_function(fn), name); } static String name(); diff --git a/newtypes.cpp b/newtypes.cpp index bf50238e..0213b78e 100644 --- a/newtypes.cpp +++ b/newtypes.cpp @@ -22,131 +22,133 @@ namespace py { namespace { -PyObject* call(PyObject* instance, PyObject* (TypeObjectBase::*f)(PyObject*) const) -{ - try - { - return (static_cast(instance->ob_type)->*f)(instance); - } - catch(...) - { - handle_exception(); - return 0; - } -} + using detail::TypeObjectBase; -// Naming this differently allows us to use it for functions returning long on -// compilers without partial ordering -template -R int_call(PyObject* instance, R (TypeObjectBase::*f)(PyObject*) const) -{ - try - { - return (static_cast(instance->ob_type)->*f)(instance); - } - catch(...) - { - handle_exception(); - return -1; - } -} + PyObject* call(PyObject* instance, PyObject* (TypeObjectBase::*f)(PyObject*) const) + { + try + { + return (static_cast(instance->ob_type)->*f)(instance); + } + catch(...) + { + handle_exception(); + return 0; + } + } -// Implemented in terms of int_call, above -int call(PyObject* instance, int (TypeObjectBase::*f)(PyObject*) const) -{ - return int_call(instance, f); -} + // Naming this differently allows us to use it for functions returning long on + // compilers without partial ordering + template + R int_call(PyObject* instance, R (TypeObjectBase::*f)(PyObject*) const) + { + try + { + return (static_cast(instance->ob_type)->*f)(instance); + } + catch(...) + { + handle_exception(); + return -1; + } + } -template -PyObject* call(PyObject* instance, PyObject* (TypeObjectBase::*f)(PyObject*, A1) const, A1 a1) -{ - try - { - return (static_cast(instance->ob_type)->*f)(instance, a1); - } - catch(...) - { - handle_exception(); - return 0; - } -} + // Implemented in terms of int_call, above + int call(PyObject* instance, int (TypeObjectBase::*f)(PyObject*) const) + { + return int_call(instance, f); + } -template -int call(PyObject* instance, int (TypeObjectBase::*f)(PyObject*, A1) const, A1 a1) -{ - try - { - return (static_cast(instance->ob_type)->*f)(instance, a1); - } - catch(...) - { - handle_exception(); - return -1; - } -} + template + PyObject* call(PyObject* instance, PyObject* (TypeObjectBase::*f)(PyObject*, A1) const, A1 a1) + { + try + { + return (static_cast(instance->ob_type)->*f)(instance, a1); + } + catch(...) + { + handle_exception(); + return 0; + } + } -template -PyObject* call(PyObject* instance, PyObject* (TypeObjectBase::*f)(PyObject*, A1, A2) const, A1 a1, A2 a2) -{ - try - { - return (static_cast(instance->ob_type)->*f)(instance, a1, a2); - } - catch(...) - { - handle_exception(); - return 0; - } -} - -template -int call(PyObject* instance, int (TypeObjectBase::*f)(PyObject*, A1, A2) const, A1 a1, A2 a2) -{ - try - { - return (static_cast(instance->ob_type)->*f)(instance, a1, a2); - } - catch(...) - { - handle_exception(); - return -1; - } -} - -template -int call(PyObject* instance, int (TypeObjectBase::*f)(PyObject*, A1, A2, A3) const, A1 a1, A2 a2, A3 a3) -{ - try - { - return (static_cast(instance->ob_type)->*f)(instance, a1, a2, a3); - } - catch(...) - { - handle_exception(); - return -1; - } -} + template + int call(PyObject* instance, int (TypeObjectBase::*f)(PyObject*, A1) const, A1 a1) + { + try + { + return (static_cast(instance->ob_type)->*f)(instance, a1); + } + catch(...) + { + handle_exception(); + return -1; + } + } -int call_length_function(PyObject* instance, int (TypeObjectBase::*f)(PyObject*) const) -{ - try - { - const int outcome = - (static_cast(instance->ob_type)->*f)(instance); - - if (outcome < 0) - { - PyErr_SetString(PyExc_ValueError, "__len__() should return >= 0"); - return -1; - } - return outcome; - } - catch(...) - { - handle_exception(); - return -1; - } -} + template + PyObject* call(PyObject* instance, PyObject* (TypeObjectBase::*f)(PyObject*, A1, A2) const, A1 a1, A2 a2) + { + try + { + return (static_cast(instance->ob_type)->*f)(instance, a1, a2); + } + catch(...) + { + handle_exception(); + return 0; + } + } + + template + int call(PyObject* instance, int (TypeObjectBase::*f)(PyObject*, A1, A2) const, A1 a1, A2 a2) + { + try + { + return (static_cast(instance->ob_type)->*f)(instance, a1, a2); + } + catch(...) + { + handle_exception(); + return -1; + } + } + + template + int call(PyObject* instance, int (TypeObjectBase::*f)(PyObject*, A1, A2, A3) const, A1 a1, A2 a2, A3 a3) + { + try + { + return (static_cast(instance->ob_type)->*f)(instance, a1, a2, a3); + } + catch(...) + { + handle_exception(); + return -1; + } + } + + int call_length_function(PyObject* instance, int (TypeObjectBase::*f)(PyObject*) const) + { + try + { + const int outcome = + (static_cast(instance->ob_type)->*f)(instance); + + if (outcome < 0) + { + PyErr_SetString(PyExc_ValueError, "__len__() should return >= 0"); + return -1; + } + return outcome; + } + catch(...) + { + handle_exception(); + return -1; + } + } } // anonymous namespace diff --git a/newtypes.h b/newtypes.h index 844caa77..cf24d7d7 100644 --- a/newtypes.h +++ b/newtypes.h @@ -32,6 +32,9 @@ namespace py { class String; + +namespace detail { + class InstanceHolderBase; class TypeObjectBase : public PythonType @@ -295,8 +298,6 @@ PyObject* Reprable::instance_repr(PyObject* instance) const return Downcast(instance)->repr(); } -namespace detail { - class shared_pod_manager { typedef std::pair Holder; @@ -353,6 +354,8 @@ namespace detail { void add_capability(TypeObjectBase::Capability capability, PyTypeObject* dest); +// This macro gets the length of an array as a compile-time constant, and will +// fail to compile if the parameter is a pointer. # define PY_ARRAY_LENGTH(a) \ (sizeof(::py::detail::countof_validate(a, &(a))) ? sizeof(a) / sizeof((a)[0]) : 0) @@ -361,8 +364,7 @@ namespace detail { template inline int countof_validate(const void*, T); -} -} +}} // namespace py::detail #endif // TYPES_DWA051800_H_ diff --git a/none.h b/none.h index 10232958..37b4851c 100644 --- a/none.h +++ b/none.h @@ -12,10 +12,10 @@ # include "pyconfig.h" # include "wrap_python.h" -namespace py { +namespace py { namespace detail { inline PyObject* none() { Py_INCREF(Py_None); return Py_None; } -} +}} // namespace py::detail #endif // NONE_DWA_052000_H_ diff --git a/objects.cpp b/objects.cpp index 5de310c2..141e9ed1 100644 --- a/objects.cpp +++ b/objects.cpp @@ -97,7 +97,7 @@ Tuple::Tuple(std::size_t n) : Object(Ptr(PyTuple_New(n))) { for (std::size_t i = 0; i < n; ++i) - PyTuple_SET_ITEM(get(), i, none()); + PyTuple_SET_ITEM(get(), i, detail::none()); } Tuple::Tuple(Ptr p) diff --git a/operators.h b/operators.h index 1713aab9..a4f55f70 100644 --- a/operators.h +++ b/operators.h @@ -11,6 +11,64 @@ namespace py { namespace detail { + struct auto_operand {}; +} + +enum operator_id +{ + op_add = 0x1, + op_sub = 0x2, + op_mul = 0x4, + op_div = 0x8, + op_mod = 0x10, + op_divmod =0x20, + op_pow = 0x40, + op_lshift = 0x80, + op_rshift = 0x100, + op_and = 0x200, + op_xor = 0x400, + op_or = 0x800, + op_neg = 0x1000, + op_pos = 0x2000, + op_abs = 0x4000, + op_invert = 0x8000, + op_int = 0x10000, + op_long = 0x20000, + op_float = 0x40000, + op_str = 0x80000, + op_cmp = 0x100000 +}; + +template +struct operators {}; + +template +struct left_operand {}; + +template +struct right_operand {}; + +namespace detail +{ + template + struct operand_select + { + template + struct wrapped + { + typedef Specified type; + }; + }; + + template <> + struct operand_select + { + template + struct wrapped + { + typedef const WrappedType& type; + }; + }; template struct define_operator; diff --git a/py.h b/py.h index 4f6c1b7d..785c02f7 100644 --- a/py.h +++ b/py.h @@ -235,7 +235,7 @@ inline PyObject* to_python(bool b) inline PyObject* to_python(void) { - return py::none(); + return py::detail::none(); } inline PyObject* to_python(const char* s) diff --git a/signatures.h b/signatures.h index 08913b77..ccf5fcd5 100644 --- a/signatures.h +++ b/signatures.h @@ -12,11 +12,13 @@ # include "pyconfig.h" -namespace py { +namespace py { +namespace detail { // A stand-in for the built-in void. This one can be passed to functions and // (under MSVC, which has a bug, be used as a default template type parameter). struct Void {}; +} // An envelope in which type information can be delivered for the purposes // of selecting an overloaded from_python() function. This is needed to work @@ -35,11 +37,12 @@ struct Type }; template <> -struct Type +struct Type { - typedef Void Id; + typedef py::detail::Void Id; }; +namespace detail { // These basically encapsulate a chain of types, , used to make the syntax of // add(Constructor()) work. We need to produce a unique type for each number // of non-default parameters to Constructor<>. Q: why not use a recursive @@ -89,11 +92,15 @@ inline Signature1 prepend(Type, Signature0) // signature results in a Void signature again. inline Signature0 prepend(Void, Signature0) { return Signature0(); } -template +} // namespace detail + +template struct Constructor { }; +namespace detail { + // Return value extraction: // This is just another little envelope for carrying a typedef (see Type, @@ -160,6 +167,6 @@ ReturnValue return_value(R (T::*)(A1, A2, A3, A4) const) { return ReturnValue template ReturnValue return_value(R (T::*)(A1, A2, A3, A4, A5) const) { return ReturnValue(); } -} +}} // namespace py::detail #endif diff --git a/singleton.h b/singleton.h index 5e510df7..d6786ada 100644 --- a/singleton.h +++ b/singleton.h @@ -11,7 +11,7 @@ # include "pyconfig.h" -namespace py { +namespace py { namespace detail { struct Empty {}; template @@ -48,6 +48,6 @@ Derived* Singleton::singleton() return &x; } -} +}} // namespace py::detail #endif diff --git a/subclass.cpp b/subclass.cpp index f92ba54f..3219ec4e 100644 --- a/subclass.cpp +++ b/subclass.cpp @@ -62,21 +62,21 @@ namespace { // PyObject* class_reduce(PyObject* klass) { - return PyObject_GetAttrString(klass, "__name__"); + return PyObject_GetAttrString(klass, const_cast("__name__")); } Ptr global_class_reduce() { - static Ptr result(py::new_wrapped_function(class_reduce)); + static Ptr result(detail::new_wrapped_function(class_reduce)); return result; } Tuple instance_reduce(PyObject* instance) { - Ptr instance_class(PyObject_GetAttrString(instance, "__class__")); + Ptr instance_class(PyObject_GetAttrString(instance, const_cast("__class__"))); - Ptr getinitargs(PyObject_GetAttrString(instance, "__getinitargs__"), + Ptr getinitargs(PyObject_GetAttrString(instance, const_cast("__getinitargs__")), Ptr::null_ok); PyErr_Clear(); Ptr initargs; @@ -90,7 +90,7 @@ namespace { initargs = Ptr(PyTuple_New(0)); } - Ptr getstate(PyObject_GetAttrString(instance, "__getstate__"), + Ptr getstate(PyObject_GetAttrString(instance, const_cast("__getstate__")), Ptr::null_ok); PyErr_Clear(); if (getstate.get() != 0) @@ -99,7 +99,7 @@ namespace { return Tuple(instance_class, initargs, state); } - Ptr state(PyObject_GetAttrString(instance, "__dict__"), Ptr::null_ok); + Ptr state(PyObject_GetAttrString(instance, const_cast("__dict__")), Ptr::null_ok); PyErr_Clear(); if (state.get() != 0 && Dict(state).size() > 0) { @@ -111,7 +111,7 @@ namespace { Ptr global_instance_reduce() { - static Ptr result(py::new_wrapped_function(instance_reduce)); + static Ptr result(detail::new_wrapped_function(instance_reduce)); return result; } } @@ -120,7 +120,7 @@ namespace { namespace detail { ClassBase::ClassBase(PyTypeObject* meta_class, String name, Tuple bases, const Dict& name_space) - : py::TypeObjectBase(meta_class), + : TypeObjectBase(meta_class), m_name(name), m_bases(bases), m_name_space(name_space) @@ -319,7 +319,7 @@ namespace detail { } Instance::Instance(PyTypeObject* class_) - : PythonObject(class_) + : py::detail::BaseObject(class_) { } @@ -348,7 +348,7 @@ PyObject* Instance::getattr(const char* name, bool use_special_function) if (!PY_CSTD_::strcmp(name, "__reduce__")) { - return new BoundFunction(Ptr(this, Ptr::new_ref), global_instance_reduce()); + return new detail::BoundFunction(Ptr(this, Ptr::new_ref), global_instance_reduce()); } Ptr local_attribute = m_name_space.get_item(String(name).reference()); @@ -418,7 +418,7 @@ PyObject* Instance::getattr(const char* name, bool use_special_function) } else { - return BoundFunction::create(Ptr(this, Ptr::borrowed), class_attribute); + return detail::BoundFunction::create(Ptr(this, Ptr::borrowed), class_attribute); } } @@ -712,52 +712,52 @@ namespace { struct NamedCapability { const char* name; - TypeObjectBase::Capability capability; + detail::TypeObjectBase::Capability capability; }; const NamedCapability enablers[] = { - { "__hash__", TypeObjectBase::hash }, - { "__cmp__", TypeObjectBase::compare }, - { "__repr__", TypeObjectBase::repr }, - { "__str__", TypeObjectBase::str }, - { "__call__", TypeObjectBase::call }, - { "__getattr__", TypeObjectBase::getattr }, - { "__setattr__", TypeObjectBase::setattr }, - { "__len__", TypeObjectBase::mapping_length }, - { "__len__", TypeObjectBase::sequence_length }, - { "__getitem__", TypeObjectBase::mapping_subscript }, - { "__getitem__", TypeObjectBase::sequence_item }, - { "__setitem__", TypeObjectBase::mapping_ass_subscript }, - { "__setitem__", TypeObjectBase::sequence_ass_item }, - { "__delitem__", TypeObjectBase::mapping_ass_subscript }, - { "__delitem__", TypeObjectBase::sequence_ass_item }, - { "__getslice__", TypeObjectBase::sequence_slice }, - { "__setslice__", TypeObjectBase::sequence_ass_slice }, - { "__delslice__", TypeObjectBase::sequence_ass_slice }, - { "__add__", TypeObjectBase::number_add }, - { "__sub__", TypeObjectBase::number_subtract }, - { "__mul__", TypeObjectBase::number_multiply }, - { "__div__", TypeObjectBase::number_divide }, - { "__mod__", TypeObjectBase::number_remainder }, - { "__divmod__", TypeObjectBase::number_divmod }, - { "__pow__", TypeObjectBase::number_power }, - { "__neg__", TypeObjectBase::number_negative }, - { "__pos__", TypeObjectBase::number_positive }, - { "__abs__", TypeObjectBase::number_absolute }, - { "__nonzero__", TypeObjectBase::number_nonzero }, - { "__invert__", TypeObjectBase::number_invert }, - { "__lshift__", TypeObjectBase::number_lshift }, - { "__rshift__", TypeObjectBase::number_rshift }, - { "__and__", TypeObjectBase::number_and }, - { "__xor__", TypeObjectBase::number_xor }, - { "__or__", TypeObjectBase::number_or }, - { "__coerce__", TypeObjectBase::number_coerce }, - { "__int__", TypeObjectBase::number_int }, - { "__long__", TypeObjectBase::number_long }, - { "__float__", TypeObjectBase::number_float }, - { "__oct__", TypeObjectBase::number_oct }, - { "__hex__", TypeObjectBase::number_hex } + { "__hash__", detail::TypeObjectBase::hash }, + { "__cmp__", detail::TypeObjectBase::compare }, + { "__repr__", detail::TypeObjectBase::repr }, + { "__str__", detail::TypeObjectBase::str }, + { "__call__", detail::TypeObjectBase::call }, + { "__getattr__", detail::TypeObjectBase::getattr }, + { "__setattr__", detail::TypeObjectBase::setattr }, + { "__len__", detail::TypeObjectBase::mapping_length }, + { "__len__", detail::TypeObjectBase::sequence_length }, + { "__getitem__", detail::TypeObjectBase::mapping_subscript }, + { "__getitem__", detail::TypeObjectBase::sequence_item }, + { "__setitem__", detail::TypeObjectBase::mapping_ass_subscript }, + { "__setitem__", detail::TypeObjectBase::sequence_ass_item }, + { "__delitem__", detail::TypeObjectBase::mapping_ass_subscript }, + { "__delitem__", detail::TypeObjectBase::sequence_ass_item }, + { "__getslice__", detail::TypeObjectBase::sequence_slice }, + { "__setslice__", detail::TypeObjectBase::sequence_ass_slice }, + { "__delslice__", detail::TypeObjectBase::sequence_ass_slice }, + { "__add__", detail::TypeObjectBase::number_add }, + { "__sub__", detail::TypeObjectBase::number_subtract }, + { "__mul__", detail::TypeObjectBase::number_multiply }, + { "__div__", detail::TypeObjectBase::number_divide }, + { "__mod__", detail::TypeObjectBase::number_remainder }, + { "__divmod__", detail::TypeObjectBase::number_divmod }, + { "__pow__", detail::TypeObjectBase::number_power }, + { "__neg__", detail::TypeObjectBase::number_negative }, + { "__pos__", detail::TypeObjectBase::number_positive }, + { "__abs__", detail::TypeObjectBase::number_absolute }, + { "__nonzero__", detail::TypeObjectBase::number_nonzero }, + { "__invert__", detail::TypeObjectBase::number_invert }, + { "__lshift__", detail::TypeObjectBase::number_lshift }, + { "__rshift__", detail::TypeObjectBase::number_rshift }, + { "__and__", detail::TypeObjectBase::number_and }, + { "__xor__", detail::TypeObjectBase::number_xor }, + { "__or__", detail::TypeObjectBase::number_or }, + { "__coerce__", detail::TypeObjectBase::number_coerce }, + { "__int__", detail::TypeObjectBase::number_int }, + { "__long__", detail::TypeObjectBase::number_long }, + { "__float__", detail::TypeObjectBase::number_float }, + { "__oct__", detail::TypeObjectBase::number_oct }, + { "__hex__", detail::TypeObjectBase::number_hex } }; bool is_prefix(const char* s1, const char* s2) diff --git a/subclass.h b/subclass.h index 68a2a1f4..a7eba973 100644 --- a/subclass.h +++ b/subclass.h @@ -20,7 +20,8 @@ namespace py { // A simple type which acts something like a built-in Python class instance. -class Instance : public PythonObject +class Instance + : public py::detail::PythonObject { public: Instance(PyTypeObject* class_); @@ -83,7 +84,7 @@ class Instance : public PythonObject template class MetaClass; namespace detail { - class ClassBase : public py::TypeObjectBase + class ClassBase : public TypeObjectBase { public: ClassBase(PyTypeObject* meta_class, String name, Tuple bases, const Dict& name_space); @@ -185,7 +186,11 @@ class Class // The type of a Class object. template class MetaClass - : public Reprable > > > > >, + : public py::detail::Reprable< + py::detail::Callable< + py::detail::Getattrable< + py::detail::Setattrable< + py::detail::TypeObject > > > > >, boost::noncopyable { public: @@ -195,7 +200,9 @@ class MetaClass PyObject* call(PyObject* args, PyObject* keywords); struct TypeObject - : Singleton > > + : py::detail::Singleton > > { TypeObject() : SingletonBase(&PyType_Type) {} };