1=================================== 2 Boost.Python_ Internals |(logo)|__ 3=================================== 4 5.. |(logo)| image:: ../../../boost.png 6 :alt: Boost 7 :class: boost-logo 8 9__ ../../../index.htm 10 11.. _`Boost.Python`: index.html 12 13.. _license: ../../../LICENSE_1_0.txt 14 15 16------------------------------------------------------- 17A conversation between Brett Calcott and David Abrahams 18------------------------------------------------------- 19 20:copyright: Copyright David Abrahams and Brett Calcott 2003. See 21 accompanying license_ for terms of use. 22 23In both of these cases, I'm quite capable of reading code - but the 24thing I don't get from scanning the source is a sense of the 25architecture, both structurally, and temporally (er, I mean in what 26order things go on). 27 281) What happens when you do the following:: 29 30 struct boring {}; 31 ...etc... 32 class_<boring>("boring") 33 ; 34 35There seems to be a fair bit going on. 36 37 - Python needs a new ClassType to be registered. 38 - We need to construct a new type that can hold our boring struct. 39 - Inward and outward converters need to be registered for the type. 40 41Can you gesture in the general direction where these things are done? 42 43 I only have time for a "off-the-top-of-my-head" answer at the moment; 44 I suggest you step through the code with a debugger after reading this 45 to see how it works, fill in details, and make sure I didn't forget 46 anything. 47 48 A new (Python) subclass of Boost.Python.Instance (see 49 libs/python/src/object/class.cpp) is created by invoking 50 Boost.Python.class, the metatype:: 51 52 >>> boring = Boost.Python.class( 53 ... 'boring' 54 ... , bases_tuple # in this case, just () 55 ... , { 56 ... '__module__' : module_name 57 ... , '__doc__' : doc_string # optional 58 ... } 59 ... ) 60 61 A handle to this object is stuck in the m_class_object field 62 of the registration associated with ``typeid(boring)``. The 63 registry will keep that object alive forever, even if you 64 wipe out the 'boring' attribute of the extension module 65 (probably not a good thing). 66 67 Because you didn't specify ``class<boring, non_copyable, 68 ...>``, a to-python converter for boring is registered which 69 copies its argument into a value_holder held by the the 70 Python boring object. 71 72 Because you didn't specify ``class<boring ...>(no_init)``, 73 an ``__init__`` function object is added to the class 74 dictionary which default-constructs a boring in a 75 value_holder (because you didn't specify some smart pointer 76 or derived wrapper class as a holder) held by the Python 77 boring object. 78 79 ``register_class_from_python`` is used to register a 80 from-python converter for ``shared_ptr<boring>``. 81 ``boost::shared_ptr``\ s are special among smart pointers 82 because their Deleter argument can be made to manage the 83 whole Python object, not just the C++ object it contains, no 84 matter how the C++ object is held. 85 86 If there were any ``bases<>``, we'd also be registering the 87 relationship between these base classes and boring in the 88 up/down cast graph (``inheritance.[hpp/cpp]``). 89 90 In earlier versions of the code, we'd be registering lvalue 91 from-python converters for the class here, but now 92 from-python conversion for wrapped classes is handled as a 93 special case, before consulting the registry, if the source 94 Python object's metaclass is the Boost.Python metaclass. 95 96 Hmm, that from-python converter probably ought to be handled 97 the way class converters are, with no explicit conversions 98 registered. 99 1002) Can you give a brief overview of the data structures that are 101 present in the registry 102 103 The registry is simple: it's just a map from typeid -> 104 registration (see boost/python/converter/registrations.hpp). 105 ``lvalue_chain`` and ``rvalue_chain`` are simple endogenous 106 linked lists. 107 108 If you want to know more, just ask. 109 110 If you want to know about the cast graph, ask me something specific in 111 a separate message. 112 113 and an overview of the process that happens as a type makes its 114 way from c++ to python and back again. 115 116 Big subject. I suggest some background reading: look for relevant 117 info in the LLNL progress reports and the messages they link to. 118 Also, 119 120 http://mail.python.org/pipermail/c++-sig/2002-May/001023.html 121 122 http://mail.python.org/pipermail/c++-sig/2002-December/003115.html 123 124 http://aspn.activestate.com/ASPN/Mail/Message/1280898 125 126 http://mail.python.org/pipermail/c++-sig/2002-July/001755.html 127 128 from c++ to python: 129 130 It depends on the type and the call policies in use or, for 131 ``call<>(...)``, ``call_method<>(...)``, or ``object(...)``, if 132 ``ref`` or ``ptr`` is used. There are also two basic 133 categories to to-python conversion, "return value" conversion 134 (for Python->C++ calls) and "argument" conversion (for 135 C++->Python calls and explicit ``object()`` conversions). The 136 behavior of these two categories differs subtly in various ways 137 whose details I forget at the moment. You can probably find 138 the answers in the above references, and certainly in the code. 139 140 The "default" case is by-value (copying) conversion, which uses 141 to_python_value as a to-python converter. 142 143 Since there can sensibly be only one way to convert any type 144 to python (disregarding the idea of scoped registries for the 145 moment), it makes sense that to-python conversions can be 146 handled by specializing a template. If the type is one of 147 the types handled by a built-in conversion 148 (builtin_converters.hpp), the corresponding template 149 specialization of to_python_value gets used. 150 151 Otherwise, to_python_value uses the ``m_to_python`` 152 function in the registration for the C++ type. 153 154 Other conversions, like by-reference conversions, are only 155 available for wrapped classes, and are requested explicitly by 156 using ``ref(...)``, ``ptr(...)``, or by specifying different 157 CallPolicies for a call, which can cause a different to-python 158 converter to be used. These conversions are never registered 159 anywhere, though they do need to use the registration to find 160 the Python class corresponding to the C++ type being referred 161 to. They just build a new Python instance and stick the 162 appropriate Holder instance in it. 163 164 165 from python to C++: 166 167 Once again I think there is a distinction between "return value" 168 and "argument" conversions, and I forget exactly what that is. 169 170 What happens depends on whether an lvalue conversion is needed 171 (see http://mail.python.org/pipermail/c++-sig/2002-May/001023.html) 172 All lvalue conversions are also registered in a type's rvalue 173 conversion chain, since when an rvalue will do, an lvalue is 174 certainly good enough. 175 176 An lvalue conversion can be done in one step (just get me the 177 pointer to the object - it can be ``NULL`` if no conversion is 178 possible) while an rvalue conversion requires two steps to 179 support wrapped function overloading and multiple converters for 180 a given C++ target type: first tell me if a conversion is 181 possible, then construct the converted object as a second step. 182 183