Boost.Python - ObjectWrapper Concept

###  | # Boost.Python ## ObjectWrapper and TypeWrapper Concepts

Introduction
Concept Requirements
  ObjectWrapper Concept
  TypeWrapper Concept
Caveat

## Introduction

This page defines two concepts used to describe classes which manage a Python objects, and which are intended to support usage with a Python-like syntax.

## Concept Requirements

### ObjectWrapper Concept

Models of the ObjectWrapper concept have object as a publicly-accessible base class, and are used to supply special construction behavior and/or additional convenient functionality through (often templated) member functions. Except when the return type `R` is itself an TypeWrapper, a member function invocation of the form

    x.some_function(a1, a2,...an)

always has semantics equivalent to:

    extract<R>(x.attr("some_function")(object(a1), object(a2),...object(an)))()

When the `R` is an TypeWrapper, the result type may be constructed by taking direct posession of:

    x.attr("some_function")(object(a1), object(a2),...object(an)).ptr()

[see caveat below]

### TypeWrapper Concept

TypeWrapper is a refinement of ObjectWrapper which is associated with a particular Python type `X`. For a given TypeWrapper `T`, a valid constructor expression

    T(a1, a2,...an)

builds a new `T` object managing the result of invoking `X` with arguments corresponding to

    object(a1), object(a2),...object(an)

When used as arguments to wrapped C++ functions, or as the template parameter to `extract<>`, only instances of the associated Python type will be considered a match.

### Caveat

The upshot of the special member function invocation rules when the return type is a TypeWrapper is that it is possible for the returned object to manage a Python object of an inappropriate type. This is not usually a serious problem; the worst-case result is that errors will be detected at runtime a little later than they might otherwise be. For an example of how this can occur, note that the `dict` member function `items` returns an object of type `list`. Now suppose the user defines this `dict` subclass in Python:

    >>> class mydict(dict):
    ...     def items(self):
    ...         return tuple(dict.items(self)) # return a tuple

Since an instance of `mydict` is also an instance of `dict`, when used as an argument to a wrapped C++ function, `boost::python::dict` can accept objects of Python type `mydict`. Invoking `items()` on this object can result in an instance of `boost::python::list` which actually holds a Python tuple. Subsequent attempts to use list methods (e.g. `append`, or any other mutating operation) on this object will raise the same exception that would occur if you tried to do it from Python.

Revised 13 November, 2002

© Copyright Dave Abrahams 2002.