...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
One point which isn't emphasized in that document is that there
are subtle differences in the way from_python
conversions
work when used for C++ function arguments and Python function return
values. In particular, while T const&
arguments may
invoke rvalue converters, a reference-to-const return value requires
an lvalue converter, since a temporary conversion result would leave
the returned reference dangling.
I'm not particularly pleased with the current callback interface, since it usually results in constructs like:
return returning<X&>::call(f, obj);However, I think the following may be possible and I plan to investigate:
return apply<X&>(f, obj);I'm open to suggestion for better names (and syntaxes)!
value_holder_generator
and
pointer_holder_generator<>
to specify the class
actually held. This move began to put pressure on the
class_<>
interface, since the need for the user to
produce complicated instantations of
class_<>
was increased:
class<Foo, bases<>, value_holder_generator<Foo_callback> >("Foo") .def("hello", &Foo::hello) ...
Unfortunately, in the case of abstract classes (and other types
without a publicly-accessible copy constructor), instantiating this
conversion function causes a compilation error. In order to support
non-copyable classes, there had to be some way to prevent the library
from trying to instantiate the conversion function. The only practical
approach I could think of was to add an additional template parameter
to the class_<>
interface. When the number of
template parameters with useful defaults begins to grow, it is often
hard to choose an order which allows users to take advantage of the
defaults.
This was the straw that broke the
class_<>
interface's back and caused the redesign
whose outcome is detailed here.
The approach allows the user to supply the optional parameters in an
arbitrary order. It was inspired by the use of named
template parameters in the Boost Iterator Adaptor
Library, though in this case it is possible to deduce the meaning
of the template parameters entirely from their type properties,
resulting in a simpler interface. Although the move from a
policy-based design to what resembles a configuration DSL usually
implies a loss of flexibility, in this case I think any costs are far
outweighed by the advantages.
Note: working around the limitations of the various compilers I'm supporting was non-trivial, and resulted in a few messy implementation details. It might be a good idea to switch to a more-straightforward approach once Metrowerks CodeWarrior Pro8 is released.
from_python
converters for a type U
which in
turn use from_python
converters registered for a type
T
where there exists a implicit conversion from
T
to U
. The current implementation is
subject to two inefficiencies:
from_python
converter produces two
pieces of data (a function and a void*
) from its
convertible()
function, we end up calling the function
for T
twice: once when the converter is looked up in the
registry, and again when the conversion is actually performed.
T
to
U
and U
to T
converters
continually search through one-another.
args<>
and bases<>
from unnamed namespace to boost::python
in their own header files.
NULL
pointers returned from wrapped C++ functions to None
.
boost/python/detail/eval.hpp
in favor of
more-general boost/mpl/apply.hpp
.
enum
types.
CallPolicy
interface for constructors of wrapped
classes
char
types.
Revised 13 November, 2002
© Copyright Dave Abrahams 2002.