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. All Rights Reserved.

Permission to copy, use, modify, sell and distribute this software is granted provided this copyright notice appears in all copies. This software is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.