diff --git a/extclass.h b/extclass.h index 8ea466cc..2655dd92 100644 --- a/extclass.h +++ b/extclass.h @@ -89,9 +89,7 @@ class ExtensionClassBase : public Class protected: void add_method(PyPtr method, const char* name); - void add_default_method(PyPtr method, const char* name); void add_method(Function* method, const char* name); - void add_default_method(Function* method, const char* name); void add_constructor_object(Function*); void add_setter_method(Function*, const char* name); @@ -139,18 +137,18 @@ class PyExtensionClassConverters // not copyable? Apparently there is no problem with g++ or MSVC unless this // is actually used. With a conforming compiler we will have a problem. friend PyObject* to_python(const T& x) - { - py::PyPtr result(create_instance(false)); - result->add_implementation( - std::auto_ptr( - new py::InstanceValueHolder(result.get(), x))); - return result.release(); - } + { + py::PyPtr result(create_instance()); + result->add_implementation( + std::auto_ptr( + new py::InstanceValueHolder(result.get(), x))); + return result.release(); + } #else friend py::Type py_holder_type(const T&) { return py::Type(); } #endif - + // Convert to T* friend T* from_python(PyObject* obj, py::Type) { @@ -194,27 +192,23 @@ class PyExtensionClassConverters template static PyObject* ptr_to_python(PtrType x) - { - py::PyPtr result(create_instance(true)); - result->add_implementation( - std::auto_ptr( - new py::InstancePtrHolder(x))); - return result.release(); - } + { + py::PyPtr result(create_instance()); + result->add_implementation( + std::auto_ptr( + new py::InstancePtrHolder(x))); + return result.release(); + } - static py::PyPtr create_instance(bool seek_base) - { - if (py::ClassRegistry::class_object() == 0) - py::report_missing_class_object(typeid(T)); + static py::PyPtr create_instance() + { + PyTypeObject* class_object = py::ClassRegistry::class_object(); + if (class_object == 0) + py::report_missing_class_object(typeid(T)); - py::Class* class_ - = seek_base && py::ClassRegistry::class_object()->bases().size() > 0 - ? py::Downcast >( - py::ClassRegistry::class_object()->bases()[0].get()).get() - : py::ClassRegistry::class_object(); - - return py::PyPtr(new py::ExtensionInstance(class_)); - } + return py::PyPtr( + new py::ExtensionInstance(class_object)); + } // Convert to const T* friend const T* from_python(PyObject* p, py::Type) @@ -374,8 +368,7 @@ class ExtensionClass template void def(Fn fn, const char* name, DefaultFn default_fn) { - this->add_default_method(new_wrapped_function(default_fn), name); - this->add_method(new_wrapped_function(fn), name); + this->add_method(py::detail::new_virtual_function(Type(), fn, default_fn), name); } // Provide a function which implements x., reading from the given @@ -420,11 +413,8 @@ class ExtensionClass detail::BaseClassInfo baseInfo(base, &detail::DefineConversion::downcast_ptr); ClassRegistry::register_base_class(baseInfo); - - Class* target = (bases().size() == 0) - ? this - : Downcast >(bases()[0].get()).get(); - target->add_base(Ptr(as_object(base), Ptr::new_ref)); + + this->add_base(Ptr(as_object(base), Ptr::new_ref)); detail::DerivedClassInfo derivedInfo(this, &detail::DefineConversion::upcast_ptr); @@ -441,11 +431,7 @@ class ExtensionClass detail::BaseClassInfo baseInfo(base, 0); ClassRegistry::register_base_class(baseInfo); - Class* target = (bases().size() == 0) - ? this - : Downcast >(bases()[0].get()).get(); - target->add_base(Ptr(as_object(base), Ptr::new_ref)); - + this->add_base(Ptr(as_object(base), Ptr::new_ref)); detail::DerivedClassInfo derivedInfo(this, &detail::DefineConversion::upcast_ptr); @@ -476,34 +462,44 @@ class HeldInstance : public T // There are no member functions: we want to avoid inadvertently overriding // any virtual functions in T. public: - HeldInstance(PyObject* p) : T(), m_self(p) {} + HeldInstance(PyObject*) : T() {} template - HeldInstance(PyObject* p, A1 a1) : T(a1), m_self(p) {} + HeldInstance(PyObject*, A1 a1) : T(a1) {} template - HeldInstance(PyObject* p, A1 a1, A2 a2) : T(a1, a2), m_self(p) {} + HeldInstance(PyObject*, A1 a1, A2 a2) : T(a1, a2) {} template - HeldInstance(PyObject* p, A1 a1, A2 a2, A3 a3) : T(a1, a2, a3), m_self(p) {} + HeldInstance(PyObject*, A1 a1, A2 a2, A3 a3) : T(a1, a2, a3) {} template - HeldInstance(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4) : T(a1, a2, a3, a4), m_self(p) {} + HeldInstance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : T(a1, a2, a3, a4) {} template - HeldInstance(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : T(a1, a2, a3, a4, a5), m_self(p) {} -protected: - PyObject* m_self; // Not really needed; doesn't really hurt. + HeldInstance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : T(a1, a2, a3, a4, a5) {} }; +// Abstract base class for all instance holders. Base for template class +// InstanceHolder<>, below. class InstanceHolderBase { public: virtual ~InstanceHolderBase() {} + virtual bool held_by_value() = 0; }; +// Abstract base class which holds a Held, somehow. Provides a uniform way to +// get a pointer to the held object template class InstanceHolder : public InstanceHolderBase { public: virtual Held *target() = 0; }; - + +// Concrete class which holds a Held by way of a wrapper class Wrapper. If Held +// can be constructed with arguments (A1...An), Wrapper must have a +// corresponding constructor for arguments (PyObject*, A1...An). Wrapper is +// neccessary to implement virtual function callbacks (there must be a +// back-pointer to the actual Python object so that we can call any +// overrides). HeldInstance (above) is used as a default Wrapper class when +// there are no virtual functions. template class InstanceValueHolder : public InstanceHolder { @@ -528,10 +524,17 @@ public: template InstanceValueHolder(ExtensionInstance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : m_held(p, a1, a2, a3, a4, a5) {} -private: + + public: // implementation of InstanceHolderBase required interface + bool held_by_value() { return true; } + + private: Wrapper m_held; }; +// Concrete class which holds a HeldType by way of a (possibly smart) pointer +// PtrType. By default, these are only generated for PtrType == +// std::auto_ptr and PtrType == boost::shared_ptr. template class InstancePtrHolder : public InstanceHolder { @@ -540,6 +543,9 @@ class InstancePtrHolder : public InstanceHolder PtrType& ptr() { return m_ptr; } InstancePtrHolder(PtrType ptr) : m_ptr(ptr) {} + + public: // implementation of InstanceHolderBase required interface + bool held_by_value() { return false; } private: PtrType m_ptr; };