###

# Boost.Python

## Header <boost/python/lvalue_from_pytype.hpp>

## Contents

Introduction
Classes
  Class Template `lvalue_from_pytype`
    Class Template `lvalue_from_pytype` synopsis
    Class Template `lvalue_from_pytype` constructor
  Class Template `extract_identity`
    Class Template `extract_identity` synopsis
    Class Template `extract_identity` static functions
  Class Template `extract_member`
    Class Template `extract_member` synopsis
    Class Template `extract_member` static functions
Example

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

## Classes

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

`lvalue_from_pytype` Requirements
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.

#### Class template `lvalue_from_pytype` synopsis

    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.

#### Class template `extract_identity` synopsis

    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.

#### Class template `extract_member` synopsis

    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 `Noddy`s. 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`.

### C++ module definition

    #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>();
    }

### Python code

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

Revised 20 November, 2002

© Copyright Dave Abrahams 2002.