This hierarchy contains converter handle classes. +-------------+ | noncopyable | +-------------+ ^ | A common base class used so that +--------+--------+ conversions can be linked into a | conversion_base | chain for efficient argument +-----------------+ conversion ^ | +---------+-----------+ | | +-----------+----+ +------+-------+ only used for | unwrap_more | | wrap_more | chaining, and don't manage any +----------------+ +--------------+ resources. ^ ^ | | +-----+-----+ +-------+-+ These converters are what users | unwrap | | wrap | actually touch, but they do so +-----------+ +---------+ through a type generator which minimizes the number of converters that must be generated, so they Each unwrap, unwrap_more, wrap, wrap_more converter holds a reference to an appropriate converter object This hierarchy contains converter body classes Exposes use/release which are needed in case the converter +-----------+ in the registry needs to be | converter | cloned. That occurs when a +-----------+ unwrap target type is not ^ contained within the Python object. | +------------------+-----+ | | +--------+-------+ Exposes | | unwrapper_base | convertible() | +----------------+ | ^ | | | +--------+----+ +-----+-----+ | unwrapper| | wrapper| +-------------+ +-----------+ Exposes T convert(PyObject*) Exposes PyObject* convert(T) unwrap: constructed with a PyObject*, whose reference count is incremented. find the registry entry for the target type look in the collection of converters for one which claims to be able to convert the PyObject to the target type. stick a pointer to the unwrapper in the unwrap object when unwrap is queried for convertibility, it checks to see if it has a pointer to an unwrapper. on conversion, the unwrapper is asked to allocate an implementation if the unwrap object isn't already holding one. The unwrap object "takes ownership" of the unwrapper's implementation. No memory allocation will actually take place unless this is a value conversion. on destruction, the unwrapper is asked to free any implementation held by the unwrap object. No memory deallocation actually takes place unless this is a value conversion on destruction, the reference count on the held PyObject is decremented. We need to make sure that by default, you can't instantiate callback<> for reference and pointer return types: although the unwrappers may exist, they may convert by-value, which would cause the referent to be destroyed upon return. wrap: find the registry entry for the source type see if there is a converter. If found, stick a pointer to it in the wrap object. when queried for convertibility, it checks to see if it has a pointer to a converter. on conversion, a reference to the target PyObject is held by the converter. Generally, the PyObject will have been created by the converter, but in certain cases it may be a pre-existing object, whose reference count will have been incremented. when a wrap x is used to return from a C++ function, x.release() is returned so that x no longer holds a reference to the PyObject when destroyed. Otherwise, on destruction, any PyObject still held has its reference-count decremented. When a converter is created by the user, the appropriate element must be added to the registry; when it is destroyed, it must be removed from the registry.