Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

boost/python/lvalue_from_pytype.hpp

Introduction
Class template lvalue_from_pytype
Class template extract_identity
Class template extract_member
Example

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

Effects

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

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);
   };
}}
InstanceType& execute(InstanceType& c);

Returns

c

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);
   };
}}
static MemberType& execute(InstanceType& c);

Returns

c.*member

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

PrevUpHomeNext