Update Python docs on builtin slots
This commit is contained in:
parent
f778ee19df
commit
4f681f751d
3 changed files with 110 additions and 48 deletions
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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:<slot>"),
|
||||||
|
where <slot> 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 >= 0x03020000
|
||||||
|
static Py_hash_t myHashFunc(PyObject *pyobj)
|
||||||
|
#else
|
||||||
|
static long myHashFunc(PyObject *pyobj)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
MyClass *cobj;
|
||||||
|
// Convert pyobj to cobj
|
||||||
|
return (cobj->field1 * (cobj->field2 << 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 < 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>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue