1[section boost/python/lvalue_from_pytype.hpp]
2[section Introduction]
3<boost/python/lvalue_from_pytype.hpp> supplies a facility for extracting C++ objects from within Python instances of a given type. This is typically useful for dealing with "traditional" Python extension types.
4[endsect]
5[section Class template `lvalue_from_pytype`]
6Class template lvalue_from_pytype will register from_python converters which, given an object of the given Python type, can extract references and pointers to a particular C++ type. Its template arguments are:
7
8 In the table below, x denotes an object of type PythonObject&
9[table
10[[Parameter][Requirements][Semantics]]
11[[Extractor][a model of [link concepts.extractor `Extractor`] whose execute function returns a reference type.][Extracts the lvalue from the Python object once its type has been confirmed]]
12[[python_type][A compile-time constant [@http://www.python.org/doc/2.2/ext/dnt-type-methods.html `PyTypeObject*`]][The Python type of instances convertible by this converter. Python subtypes are also convertible.]]
13]
14``
15namespace boost { namespace python
16{
17   template <class Extractor, PyTypeObject const* python_type>
18   struct lvalue_from_pytype
19   {
20       lvalue_from_pytype();
21   };
22}}
23``
24[section Class template `lvalue_from_pytype` constructor]
25``lvalue_from_pytype();``
26[variablelist
27[[Effects][Registers converters which can convert Python objects of the given type to lvalues of the type returned by Extractor::execute.]]
28]
29[endsect]
30[endsect]
31[section Class template `extract_identity`]
32extract_identity is a model of [link concepts.extractor `Extractor`] which can be used in the common case where the C++ type to be extracted is the same as the Python object type.
33``
34namespace boost { namespace python
35{
36   template <class InstanceType>
37   struct extract_identity
38   {
39      static InstanceType& execute(InstanceType& c);
40   };
41}}
42``
43[section Class template `extract_identity` static functions]
44``InstanceType& execute(InstanceType& c);``
45[variablelist
46[[Returns][c]]
47]
48[endsect]
49[endsect]
50[section Class template `extract_member`]
51`extract_member` is a model of [link concepts.extractor `Extractor`] which can be used in the common case in the common case where the C++ type to be extracted is a member of the Python object.
52``
53namespace boost { namespace python
54{
55   template <class InstanceType, class MemberType, MemberType (InstanceType::*member)>
56   struct extract_member
57   {
58      static MemberType& execute(InstanceType& c);
59   };
60}}
61``
62[section Class template `extract_member` static functions]
63``static MemberType& execute(InstanceType& c);``
64[variablelist
65[[Returns][`c.*member`]]
66]
67[endsect]
68[endsect]
69[section Example]
70This example presumes that someone has implemented the standard noddy example module from the Python documentation, and we want to build a module which manipulates Noddys. Since noddy_NoddyObject is so simple that it carries no interesting information, the example is a bit contrived: it assumes you want to keep track of one particular object for some reason. This module would have to be dynamically linked to the module which defines noddy_NoddyType.
71
72In C++:
73``
74#include <boost/python/module.hpp>
75#include <boost/python/handle.hpp>
76#include <boost/python/borrowed.hpp>
77#include <boost/python/lvalue_from_pytype.hpp>
78
79// definition lifted from the Python docs
80typedef struct {
81   PyObject_HEAD
82} noddy_NoddyObject;
83
84using namespace boost::python;
85static handle<noddy_NoddyObject> cache;
86
87bool is_cached(noddy_NoddyObject* x)
88{
89   return x == cache.get();
90}
91
92void set_cache(noddy_NoddyObject* x)
93{
94   cache = handle<noddy_NoddyObject>(borrowed(x));
95}
96
97BOOST_PYTHON_MODULE(noddy_cache)
98{
99   def("is_cached", is_cached);
100   def("set_cache", set_cache);
101
102   // register Noddy lvalue converter
103   lvalue_from_pytype<extract_identity<noddy_NoddyObject>,&noddy_NoddyType>();
104}
105``
106In Python:
107``
108>>> import noddy
109>>> n = noddy.new_noddy()
110>>> import noddy_cache
111>>> noddy_cache.is_cached(n)
1120
113>>> noddy_cache.set_cache(n)
114>>> noddy_cache.is_cached(n)
1151
116>>> noddy_cache.is_cached(noddy.new_noddy())
1170
118``
119[endsect]
120[endsect]
121