From c2d449d47ecb17011b7bb86f8817187e0f930d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ullrich=20K=C3=B6the?= Date: Tue, 17 Oct 2000 20:39:31 +0000 Subject: [PATCH] added explanatory comments [SVN r7979] --- extclass.cpp | 21 +++++++++++++++++++++ extclass.h | 15 +++++++++++---- subclass.h | 1 + 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/extclass.cpp b/extclass.cpp index b37979d7..28651eb8 100644 --- a/extclass.cpp +++ b/extclass.cpp @@ -218,6 +218,27 @@ ExtensionClassBase::ExtensionClassBase(const char* name) { } +/* + This function is used in from_python() to convert wrapped classes that are + related by inheritance. The problem is this: although C++ provides all necessary + conversion operators, source and target of a conversion must be known at compile + time. However, in Python we want to convert classes at runtime. The solution is to + generate conversion functions at compile time, register them within the appropriate + class objects and call them when a particular runtime conversion is required. + + If functions for any possible conversion have to be stored, their number will grow + qudratically. To reduce this number, we actually store only conversion functions + between adjacent levels in the inheritance tree. By traversing the tree recursively, + we can build any allowed conversion as a concatenation of simple conversions. This + traversal is done in the functions try_base_class_conversions() and + try_derived_class_conversions(). If a particular conversion is impossible, all + conversion functions will return a NULL pointer. + + The function extract_from_holder() attempts to actually extract the pointer to + the contained object from an InstanceHolderBase (a wrapper class). A conversion + of the held object to 'T *' is allowed when the conversion + 'dynamic_cast *>(an_instance_holder_base)' succeeds. +*/ void * ExtensionClassBase::try_class_conversions(InstanceHolderBase * object) const { void * result = try_derived_class_conversions(object); diff --git a/extclass.h b/extclass.h index 62f105ca..f1712f36 100644 --- a/extclass.h +++ b/extclass.h @@ -154,6 +154,7 @@ class PyExtensionClassConverters 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); if(target) return static_cast(target); @@ -401,11 +402,13 @@ class ExtensionClass this->def_setter(pm, name); } - // declare the given class a base class of this and register - // conversion functions + // declare the given class a base class of this one and register + // up and down conversion functions template void declare_base(ExtensionClass * base) { + // see extclass.cpp for an explanation of why we need to register + // conversion functions detail::BaseClassInfo baseInfo(base, &detail::DefineConversion::downcast_ptr); ClassRegistry::register_base_class(baseInfo); @@ -416,11 +419,13 @@ class ExtensionClass ClassRegistry::register_derived_class(derivedInfo); } - // declare the given class a base class of this and register - // only upcast function + // declare the given class a base class of this one and register + // only up conversion function template void declare_base(ExtensionClass * base, WithoutDowncast) { + // see extclass.cpp for an explanation of why we need to register + // conversion functions detail::BaseClassInfo baseInfo(base, 0); ClassRegistry::register_base_class(baseInfo); add_base(Ptr(as_object(base), Ptr::new_ref)); @@ -435,6 +440,8 @@ class ExtensionClass virtual std::vector const & base_classes() const; virtual std::vector const & derived_classes() const; + + // the purpose of this function is explained in extclass.cpp virtual void * convert_from_holder(InstanceHolderBase * v) const; template diff --git a/subclass.h b/subclass.h index 32db3b9d..0f2366b5 100644 --- a/subclass.h +++ b/subclass.h @@ -73,6 +73,7 @@ class Class int setattr(const char* name, PyObject* value); PyObject* call(PyObject* args, PyObject* keywords); + // the purpose of these functions is explained in extclass.cpp virtual void * try_class_conversions(InstanceHolderBase*) const { return 0; } virtual void * try_base_class_conversions(InstanceHolderBase*) const { return 0; } virtual void * try_derived_class_conversions(InstanceHolderBase*) const { return 0; }