## boost/python/lvalue_from_pytype.hpp

### Introduction

<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.

### Class template `lvalue_from_pytype`

Class 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:

    In the table below, x denotes an object of type PythonObject&

Parameter | Requirements | Semantics
--- | --- | ---
Extractor | a model of `Extractor` whose execute function returns a reference type. | Extracts the lvalue from the Python object once its type has been confirmed
python_type | A compile-time constant `PyTypeObject*` | The Python type of instances convertible by this converter. Python subtypes are also convertible.

    namespace boost { namespace python
    {
       template <class Extractor, PyTypeObject const* python_type>
       struct lvalue_from_pytype
       {
           lvalue_from_pytype();
       };
    }}

#### Class template `lvalue_from_pytype` constructor

    lvalue_from_pytype();

Effects

  Registers converters which can convert Python objects of the given type to lvalues of the type returned by Extractor::execute.

### Class template `extract_identity`

extract_identity is a model of `Extractor` which can be used in the common case where the C++ type to be extracted is the same as the Python object type.

    namespace boost { namespace python
    {
       template <class InstanceType>
       struct extract_identity
       {
          static InstanceType& execute(InstanceType& c);
       };
    }}

#### Class template `extract_identity` static functions

    InstanceType& execute(InstanceType& c);

Returns

  c

### Class template `extract_member`

`extract_member` is a model of `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.

    namespace boost { namespace python
    {
       template <class InstanceType, class MemberType, MemberType (InstanceType::*member)>
       struct extract_member
       {
          static MemberType& execute(InstanceType& c);
       };
    }}

#### Class template `extract_member` static functions

    static MemberType& execute(InstanceType& c);

Returns

  `c.*member`

### Example

This 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.

In C++:

    #include <boost/python/module.hpp>
    #include <boost/python/handle.hpp>
    #include <boost/python/borrowed.hpp>
    #include <boost/python/lvalue_from_pytype.hpp>

    // definition lifted from the Python docs
    typedef struct {
       PyObject_HEAD
    } noddy_NoddyObject;

    using namespace boost::python;
    static handle<noddy_NoddyObject> cache;

    bool is_cached(noddy_NoddyObject* x)
    {
       return x == cache.get();
    }

    void set_cache(noddy_NoddyObject* x)
    {
       cache = handle<noddy_NoddyObject>(borrowed(x));
    }

    BOOST_PYTHON_MODULE(noddy_cache)
    {
       def("is_cached", is_cached);
       def("set_cache", set_cache);

       // register Noddy lvalue converter
       lvalue_from_pytype<extract_identity<noddy_NoddyObject>,&noddy_NoddyType>();
    }

In Python:

    >>> import noddy
    >>> n = noddy.new_noddy()
    >>> import noddy_cache
    >>> noddy_cache.is_cached(n)
    0
    >>> noddy_cache.set_cache(n)
    >>> noddy_cache.is_cached(n)
    1
    >>> noddy_cache.is_cached(noddy.new_noddy())
    0