Update Python docs on builtin slots

This commit is contained in:
William S Fulton 2016-08-18 07:09:52 +01:00
commit 4f681f751d
3 changed files with 110 additions and 48 deletions

View file

@ -310,7 +310,7 @@
<li><a href="CPlusPlus11.html#CPlusPlus11_general_purpose_smart_pointers">General-purpose smart pointers</a> <li><a href="CPlusPlus11.html#CPlusPlus11_general_purpose_smart_pointers">General-purpose smart pointers</a>
<li><a href="CPlusPlus11.html#CPlusPlus11_extensible_random_number_facility">Extensible random number facility</a> <li><a href="CPlusPlus11.html#CPlusPlus11_extensible_random_number_facility">Extensible random number facility</a>
<li><a href="CPlusPlus11.html#CPlusPlus11_wrapper_reference">Wrapper reference</a> <li><a href="CPlusPlus11.html#CPlusPlus11_wrapper_reference">Wrapper reference</a>
<li><a href="CPlusPlus11.html#CPlusPlus11_polymorphous_wrappers_for_function_objects">Polymorphous wrappers for function objects</a> <li><a href="CPlusPlus11.html#CPlusPlus11_polymorphous_wrappers_for_function_objects">Polymorphic wrappers for function objects</a>
<li><a href="CPlusPlus11.html#CPlusPlus11_type_traits_for_metaprogramming">Type traits for metaprogramming</a> <li><a href="CPlusPlus11.html#CPlusPlus11_type_traits_for_metaprogramming">Type traits for metaprogramming</a>
<li><a href="CPlusPlus11.html#CPlusPlus11_uniform_method_for_computing_return_type_of_function_objects">Uniform method for computing return type of function objects</a> <li><a href="CPlusPlus11.html#CPlusPlus11_uniform_method_for_computing_return_type_of_function_objects">Uniform method for computing return type of function objects</a>
</ul> </ul>
@ -1529,7 +1529,7 @@
<li><a href="Python.html#Python_builtin_types">Built-in Types</a> <li><a href="Python.html#Python_builtin_types">Built-in Types</a>
<ul> <ul>
<li><a href="Python.html#Python_builtin_limitations">Limitations</a> <li><a href="Python.html#Python_builtin_limitations">Limitations</a>
<li><a href="Python.html#Python_builtin_overloads">Operator overloads -- use them!</a> <li><a href="Python.html#Python_builtin_overloads">Operator overloads and slots -- use them!</a>
</ul> </ul>
<li><a href="Python.html#Python_nn30">Memory management</a> <li><a href="Python.html#Python_nn30">Memory management</a>
<li><a href="Python.html#Python_nn31">Python 2.2 and classic classes</a> <li><a href="Python.html#Python_nn31">Python 2.2 and classic classes</a>

View file

@ -51,7 +51,7 @@
<li><a href="#Python_builtin_types">Built-in Types</a> <li><a href="#Python_builtin_types">Built-in Types</a>
<ul> <ul>
<li><a href="#Python_builtin_limitations">Limitations</a> <li><a href="#Python_builtin_limitations">Limitations</a>
<li><a href="#Python_builtin_overloads">Operator overloads -- use them!</a> <li><a href="#Python_builtin_overloads">Operator overloads and slots -- use them!</a>
</ul> </ul>
<li><a href="#Python_nn30">Memory management</a> <li><a href="#Python_nn30">Memory management</a>
<li><a href="#Python_nn31">Python 2.2 and classic classes</a> <li><a href="#Python_nn31">Python 2.2 and classic classes</a>
@ -2442,7 +2442,7 @@ assert(issubclass(B.Derived, A.Base))
</li> </li>
</ul> </ul>
<H4><a name="Python_builtin_overloads">36.4.2.2 Operator overloads -- use them!</a></H4> <H4><a name="Python_builtin_overloads">36.4.2.2 Operator overloads and slots -- use them!</a></H4>
<p>The entire justification for the <tt>-builtin</tt> option is improved <p>The entire justification for the <tt>-builtin</tt> option is improved
@ -2494,52 +2494,110 @@ automatically converted to python slot operators, refer to the file
<tt>python/pyopers.swig</tt> in the SWIG library. <tt>python/pyopers.swig</tt> in the SWIG library.
</p> </p>
<p>There are other very useful python slots that you
may explicitly define using <tt>%feature</tt> directives. For example, <p>
suppose you want to use instances of a wrapped class as keys in a native python Read about all of the available python slots here:
<tt>dict</tt>. That will work as long as you define a hash function for <a href="http://docs.python.org/c-api/typeobj.html">http://docs.python.org/c-api/typeobj.html</a></p>
instances of your class, and use it to define the python <tt>tp_hash</tt>
slot: <p>
There are two ways to define a python slot function: dispatch to a
statically defined function; or dispatch to a method defined on the
operand.
</p>
<p>
To dispatch to a statically defined function, use %feature("python:&lt;slot&gt;"),
where &lt;slot&gt; is the name of a field in a <tt>PyTypeObject, PyNumberMethods,
PyMappingMethods, PySequenceMethods</tt> or <tt>PyBufferProcs</tt>.
You may override (almost) all of these slots.
</p>
<p>
Let's consider an example setting the <tt>tp_hash</tt> slot for the <tt>MyClass</tt> type.
This is akin to providing a <tt>__hash__</tt> method (for non-builtin types) to make a type hashable.
The hashable type can then for example be added to a Python <tt>dict</tt>.
</p> </p>
<div class="code"> <div class="code">
<pre> <pre>
%feature("python:slot", "tp_hash", functype="hashfunc") Cheese::cheeseHashFunc; %feature("python:tp_hash") MyClass "myHashFunc";
class Cheese { class MyClass {
public: public:
Cheese (const char *name); long field1;
long cheeseHashFunc () const; long field2;
...
};
%{
#if PY_VERSION_HEX &gt;= 0x03020000
static Py_hash_t myHashFunc(PyObject *pyobj)
#else
static long myHashFunc(PyObject *pyobj)
#endif
{
MyClass *cobj;
// Convert pyobj to cobj
return (cobj-&gt;field1 * (cobj-&gt;field2 &lt;&lt; 7));
}
%}
</pre>
</div>
<p>
If you examine the generated code, the supplied hash function will now be
the function callback in the tp_hash slot for the builtin type for <tt>MyClass</tt>:
</p>
<div class="code">
<pre>
static PyHeapTypeObject SwigPyBuiltin__MyClass_type = {
...
(hashfunc) myHashFunc, /* tp_hash */
...
</pre>
</div>
<p>
NOTE: It is the responsibility of the programmer (that's you!) to ensure
that a statically defined slot function has the correct signature, the <tt>hashfunc</tt>
typedef in this case.
</p>
<p>
If, instead, you want to dispatch to an instance method, you can
use %feature("python:slot"). For example:
</p>
<div class="code">
<pre>
%feature("python:slot", "tp_hash", functype="hashfunc") MyClass::myHashFunc;
#if PY_VERSION_HEX &lt; 0x03020000
#define Py_hash_t long
#endif
class MyClass {
public:
Py_hash_t myHashFunc() const;
...
}; };
</pre> </pre>
</div> </div>
<p>This will allow you to write python code like this:</p> <p>
NOTE: Some python slots use a method signature which does not
match the signature of SWIG-wrapped methods. For those slots,
SWIG will automatically generate a "closure" function to re-marshal
the arguments before dispatching to the wrapped method. Setting
the "functype" attribute of the feature enables SWIG to generate
the chosen closure function.
</p>
<div class="targetlang"> <p>
<pre> There is further information on <tt>%feature("python:slot")</tt>
from my MyPackage import Cheese
inventory = {
Cheese("cheddar") : 0,
Cheese("gouda") : 0,
Cheese("camembert") : 0
}
</pre>
</div>
<p>Because you defined the <tt>tp_hash</tt> slot, <tt>Cheese</tt> objects may
be used as hash keys; and when the <tt>cheeseHashFunc</tt> method is invoked
by a python <tt>dict</tt>, it will <b>not</b> go through named method dispatch.
A more detailed discussion about <tt>%feature("python:slot")</tt> can be found
in the file <tt>python/pyopers.swig</tt> in the SWIG library. in the file <tt>python/pyopers.swig</tt> in the SWIG library.
You can read about all of the available python slots here:</p>
<p><a href="http://docs.python.org/c-api/typeobj.html">http://docs.python.org/c-api/typeobj.html</a></p>
<p>You may override (almost) all of the slots defined in the <tt>PyTypeObject,
PyNumberMethods, PyMappingMethods, PySequenceMethods</tt>, and <tt>PyBufferProcs</tt>
structs.
</p> </p>

View file

@ -19,30 +19,34 @@
PyMappingMethods, PySequenceMethods, or PyBufferProcs. For example: PyMappingMethods, PySequenceMethods, or PyBufferProcs. For example:
%{ %{
// Note: Py_hash_t was introduced in Python 3.2
static long myHashFunc (PyObject *pyobj) { static Py_hash_t myHashFunc(PyObject *pyobj) {
MyClass *cobj; MyClass *cobj;
// Convert pyobj to cobj // Convert pyobj to cobj
return (cobj->field1 * (cobj->field2 << 7)); return (cobj->field1 * (cobj->field2 << 7));
} }
%} %}
%feature("python:tp_hash") MyClass "myHashFunc"; %feature("python:tp_hash") MyClass "myHashFunc";
class MyClass {
public:
...
};
NOTE: It is the responsibility of the programmer (that's you) to ensure NOTE: It is the responsibility of the programmer (that's you) to ensure
that a statically defined slot function has the correct signature. that a statically defined slot function has the correct signature.
If, instead, you want to dispatch to an instance method, you can If, instead, you want to dispatch to an instance method, you can
use %feature("python:slot"). For example: use %feature("python:slot"). For example:
%feature("python:slot", "tp_hash", functype="hashfunc") MyClass::myHashFunc;
class MyClass { class MyClass {
public: public:
long myHashFunc () const; Py_hash_t myHashFunc () const;
... ...
}; };
%feature("python:slot", "tp_hash", functype="hashfunc") MyClass::myHashFunc;
NOTE: Some python slots use a method signature which does not NOTE: Some python slots use a method signature which does not
match the signature of SWIG-wrapped methods. For those slots, match the signature of SWIG-wrapped methods. For those slots,