Boost.Python - <wrapper.hpp>

###  | # Boost.Python ## Header <wrapper.hpp>

## Contents

Introduction
Classes
  Class template `override`
    Class `override` synopsis
    Class `override` observer functions
  Class template `wrapper`
    Class `wrapper` synopsis
    Class `wrapper` observer functions
Example(s)

## Introduction

To wrap a class `T` such that its virtual functions can be "overridden in Python"—so that the corresponding method of a Python derived class will be called when the virtual function is invoked from C++—you must create a C++ wrapper class derived from ``T`` that overrides those virtual functions so that they call into Python. This header contains classes that can be used to make that job easier.

## Classes

### Class `override`

Encapsulates a Python override of a C++ virtual function. An `override` object either holds a callable Python object or `None`.

#### Class `override` synopsis

    namespace boost
    {
      class override : object
      {
       public:
          unspecified operator() const;
          template <class A0>
          unspecified operator(A0) const;
          template <class A0, class A1>
          unspecified operator(A0, A1) const;
          ...
          template <class A0, class A1, ...class An>
          unspecified operator(A0, A1, ...An) const;
      };
    };

#### Class `override` observer functions

    unspecified operator() const;
    template <class A0>
    unspecified operator(A0) const;
    template <class A0, class A1>
    unspecified operator(A0, A1) const;
    ...
    template <class A0, class A1, ...class An>
    unspecified operator(A0, A1, ...An) const;

Effects: If `*this` holds a callable Python object, it is invoked with the specified arguments in the manner specified here. Otherwise, throws `error_already_set` .
Returns: An object of unspecified type that holds the Python result of the invocation and, when converted to a C++ type `R`, attempts to convert that result object to `R`. If that conversion fails, throws `error_already_set` .

### Class template `wrapper`

Deriving your wrapper class from both ``T`` and ``wrapper<T> makes writing that derived class easier.

#### Class template `wrapper` synopsis

    namespace boost
    {
      class wrapper
      {
       protected:
          override get_override(char const* name) const;
      };
    };

#### Class `wrapper` observer functions

    override get_override(char const* name) const;

Requires: `name` is a ntbs.
Returns: If `*this` is the C++ base class subobject of a Python derived class instance that overrides the named function, returns an `override` object that delegates to the Python override. Otherwise, returns an `override` object that holds `None`.

## Example

    #include <boost/python/module.hpp>
    #include <boost/python/class.hpp>
    #include <boost/python/wrapper.hpp>
    #include <boost/python/call.hpp>

    using namespace boost::python;

    // Class with one pure virtual function
    struct P
    {
        virtual ~P(){}
        virtual char const* f() = 0;
        char const* g() { return "P::g()"; }
    };

    struct PCallback : P, wrapper<P>
    {
        char const* f()
        {
    #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // Workaround for vc6/vc7
            return call<char const*>(this->get_override("f").ptr());
    #else
            return this->get_override("f")();
    #endif
        }
    };

    // Class with one non-pure virtual function
    struct A
    {
        virtual ~A(){}
        virtual char const* f() { return "A::f()"; }
    };

    struct ACallback :  A, wrapper<A>
    {
        char const* f()
        {
            if (override f = this->get_override("f"))
    #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // Workaround for vc6/vc7
                return call<char const*>(f.ptr());
    #else
                return f();
    #endif

            return A::f();
        }

        char const* default_f() { return this->A::f(); }
    };

    BOOST_PYTHON_MODULE_INIT(polymorphism)
    {
        class_<PCallback,boost::noncopyable>("P")
            .def("f", pure_virtual(&P::f))
            ;

        class_<ACallback,boost::noncopyable>("A")
            .def("f", &A::f, &ACallback::default_f)
            ;
    }

Revised 31 October, 2004

© Copyright Dave Abrahams 2004