2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-21 17:12:22 +00:00

added explanatory comments

[SVN r7979]
This commit is contained in:
Ullrich Köthe
2000-10-17 20:39:31 +00:00
parent dc3b9c510d
commit c2d449d47e
3 changed files with 33 additions and 4 deletions

View File

@@ -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<InstanceHolde<T> *>(an_instance_holder_base)' succeeds.
*/
void * ExtensionClassBase::try_class_conversions(InstanceHolderBase * object) const
{
void * result = try_derived_class_conversions(object);

View File

@@ -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<T>::class_object()->try_class_conversions(*p);
if(target)
return static_cast<T *>(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 <class S, class V>
void declare_base(ExtensionClass<S, V> * base)
{
// see extclass.cpp for an explanation of why we need to register
// conversion functions
detail::BaseClassInfo baseInfo(base,
&detail::DefineConversion<S, T>::downcast_ptr);
ClassRegistry<T>::register_base_class(baseInfo);
@@ -416,11 +419,13 @@ class ExtensionClass
ClassRegistry<S>::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 <class S, class V>
void declare_base(ExtensionClass<S, V> * base, WithoutDowncast)
{
// see extclass.cpp for an explanation of why we need to register
// conversion functions
detail::BaseClassInfo baseInfo(base, 0);
ClassRegistry<T>::register_base_class(baseInfo);
add_base(Ptr(as_object(base), Ptr::new_ref));
@@ -435,6 +440,8 @@ class ExtensionClass
virtual std::vector<detail::BaseClassInfo> const & base_classes() const;
virtual std::vector<detail::DerivedClassInfo> const & derived_classes() const;
// the purpose of this function is explained in extclass.cpp
virtual void * convert_from_holder(InstanceHolderBase * v) const;
template <class Signature>

View File

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