2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-31 20:32:16 +00:00

implicit conversions

[SVN r13277]
This commit is contained in:
Dave Abrahams
2002-03-26 06:38:41 +00:00
parent 11bd4c3223
commit ac34e0e108
9 changed files with 183 additions and 1 deletions

View File

@@ -21,6 +21,9 @@ BOOST_PYTHON_DECL void* find(
BOOST_PYTHON_DECL rvalue_stage1_data find(
PyObject* source, rvalue_from_python_registration const*);
BOOST_PYTHON_DECL rvalue_from_python_registration const* find_chain(
PyObject* source, rvalue_from_python_registration const*);
}}} // namespace boost::python::converter
#endif // FIND_FROM_PYTHON_DWA2002223_HPP

View File

@@ -0,0 +1,50 @@
// Copyright David Abrahams 2002. 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.
#ifndef IMPLICIT_DWA2002326_HPP
# define IMPLICIT_DWA2002326_HPP
# include <boost/python/converter/from_python_data.hpp>
# include <boost/python/converter/from_python_stage1_data.hpp>
# include <boost/python/converter/registrations.hpp>
namespace boost { namespace python { namespace converter {
template <class Source, class Target>
struct implicit
{
static void* convertible(PyObject* obj)
{
// Find a converter registration which can produce a Source
// instance from obj
return const_cast<rvalue_from_python_registration*>(
find_chain(obj, rvalue_from_python_chain<Source>::value));
}
static void construct(PyObject* obj, rvalue_stage1_data* data)
{
// This is the registration we got from the convertible step
rvalue_from_python_registration const* registration
= static_cast<rvalue_from_python_registration*>(data->convertible);
// Call the convertible function again
rvalue_data<Source> intermediate_data(registration->convertible(obj));
// Use the result to construct the source type if the first
// converter was an rvalue converter.
if (registration->construct != 0)
registration->construct(obj, &intermediate_data.stage1);
void* storage = ((rvalue_base_data<Target>*)data)->storage.bytes;
new (storage) Target(*(Source*)intermediate_data.storage.bytes);
// record successful construction
data->convertible = storage;
}
};
}}} // namespace boost::python::converter
#endif // IMPLICIT_DWA2002326_HPP

View File

@@ -0,0 +1,28 @@
// Copyright David Abrahams 2002. 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.
#ifndef IMPLICIT_DWA2002325_HPP
# define IMPLICIT_DWA2002325_HPP
# include <boost/type.hpp>
# include <boost/python/converter/implicit.hpp>
# include <boost/python/converter/registry.hpp>
# include <boost/python/converter/type_id.hpp>
namespace boost { namespace python {
template <class Source, class Target>
void implicitly_convertible(boost::type<Source>* = 0, boost::type<Target>* = 0)
{
typedef converter::implicit<Source,Target> functions;
converter::registry::insert(
&functions::convertible
, &functions::construct
, converter::undecorated_type_id<Target>());
}
}} // namespace boost::python
#endif // IMPLICIT_DWA2002325_HPP

View File

@@ -22,7 +22,7 @@ namespace detail
}
// A function generator whose static execute() function is an lvalue
// from_python converter using the given Extractor. U is exepcted to
// from_python converter using the given Extractor. U is expected to
// be the actual type of the PyObject instance from which the result
// is being extracted.
template <class Extractor, class U>

View File

@@ -29,6 +29,18 @@ BOOST_PYTHON_DECL rvalue_stage1_data find(
return data;
}
BOOST_PYTHON_DECL rvalue_from_python_registration const* find_chain(
PyObject* source
, rvalue_from_python_registration const* chain)
{
for (;chain != 0; chain = chain->next)
{
if (chain->convertible(source))
break;
}
return chain;
}
BOOST_PYTHON_DECL void* find(
PyObject* source
, lvalue_from_python_registration const* chain)

View File

@@ -57,6 +57,7 @@ bpl-test test_pointer_adoption ;
bpl-test callbacks ;
bpl-test virtual_functions ;
bpl-test back_reference ;
bpl-test implicit ;
# --- unit tests of library components ---
unit-test indirect_traits_test

37
test/implicit.cpp Normal file
View File

@@ -0,0 +1,37 @@
// Copyright David Abrahams 2002. 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.
#include <boost/python/class.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/module.hpp>
#include "test_class.hpp"
// This test shows that a class can be wrapped "as itself" but also
// acquire a back-reference iff has_back_reference<> is appropriately
// specialized.
using namespace boost::python;
typedef test_class<> X;
int x_value(X const& x)
{
return x.value();
}
BOOST_PYTHON_MODULE_INIT(implicit_ext)
{
implicitly_convertible<int,X>();
module("implicit_ext")
.def("x_value", x_value)
.add(
class_<X>("X")
.def_init(args<int>())
.def("value", &X::value)
.def("set", &X::set)
)
;
}
#include "module_tail.cpp"

20
test/implicit.py Normal file
View File

@@ -0,0 +1,20 @@
'''
>>> from implicit_ext import *
>>> x_value(X(42))
42
>>> x_value(42)
42
'''
def run(args = None):
import sys
import doctest
if args is not None:
sys.argv = args
return doctest.testmod(sys.modules.get(__name__))
if __name__ == '__main__':
print "running..."
import sys
sys.exit(run()[0])

31
test/test_class.hpp Normal file
View File

@@ -0,0 +1,31 @@
// Copyright David Abrahams 2002. 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.
#ifndef TEST_CLASS_DWA2002326_HPP
# define TEST_CLASS_DWA2002326_HPP
# include <cassert>
template <int n = 0>
struct test_class
{
explicit test_class(int x) : x(x), magic(7654321 + n) { ++counter; }
test_class(test_class const& rhs) : x(rhs.x), magic(7654321 + n) { ++counter; }
virtual ~test_class() { assert(magic == 7654321 + n); magic = 6666666; x = 9999; --counter; }
void set(int x) { assert(magic == 7654321 + n); this->x = x; }
int value() const { assert(magic == 7654321 + n); return x; }
static int count() { return counter; }
private:
void operator=(test_class const&);
private:
int x;
long magic;
static int counter;
};
template <int n>
int test_class<n>::counter;
#endif // TEST_CLASS_DWA2002326_HPP