Skip to content

Commit ac34e0e

Browse files
committed
implicit conversions
[SVN r13277]
1 parent 11bd4c3 commit ac34e0e

9 files changed

Lines changed: 183 additions & 1 deletion

File tree

include/boost/python/converter/find_from_python.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ BOOST_PYTHON_DECL void* find(
2121
BOOST_PYTHON_DECL rvalue_stage1_data find(
2222
PyObject* source, rvalue_from_python_registration const*);
2323

24+
BOOST_PYTHON_DECL rvalue_from_python_registration const* find_chain(
25+
PyObject* source, rvalue_from_python_registration const*);
26+
2427
}}} // namespace boost::python::converter
2528

2629
#endif // FIND_FROM_PYTHON_DWA2002223_HPP
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright David Abrahams 2002. Permission to copy, use,
2+
// modify, sell and distribute this software is granted provided this
3+
// copyright notice appears in all copies. This software is provided
4+
// "as is" without express or implied warranty, and with no claim as
5+
// to its suitability for any purpose.
6+
#ifndef IMPLICIT_DWA2002326_HPP
7+
# define IMPLICIT_DWA2002326_HPP
8+
# include <boost/python/converter/from_python_data.hpp>
9+
# include <boost/python/converter/from_python_stage1_data.hpp>
10+
# include <boost/python/converter/registrations.hpp>
11+
12+
namespace boost { namespace python { namespace converter {
13+
14+
template <class Source, class Target>
15+
struct implicit
16+
{
17+
static void* convertible(PyObject* obj)
18+
{
19+
// Find a converter registration which can produce a Source
20+
// instance from obj
21+
return const_cast<rvalue_from_python_registration*>(
22+
find_chain(obj, rvalue_from_python_chain<Source>::value));
23+
}
24+
25+
static void construct(PyObject* obj, rvalue_stage1_data* data)
26+
{
27+
// This is the registration we got from the convertible step
28+
rvalue_from_python_registration const* registration
29+
= static_cast<rvalue_from_python_registration*>(data->convertible);
30+
31+
// Call the convertible function again
32+
rvalue_data<Source> intermediate_data(registration->convertible(obj));
33+
34+
// Use the result to construct the source type if the first
35+
// converter was an rvalue converter.
36+
if (registration->construct != 0)
37+
registration->construct(obj, &intermediate_data.stage1);
38+
39+
void* storage = ((rvalue_base_data<Target>*)data)->storage.bytes;
40+
new (storage) Target(*(Source*)intermediate_data.storage.bytes);
41+
42+
// record successful construction
43+
data->convertible = storage;
44+
45+
}
46+
};
47+
48+
}}} // namespace boost::python::converter
49+
50+
#endif // IMPLICIT_DWA2002326_HPP

include/boost/python/implicit.hpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright David Abrahams 2002. Permission to copy, use,
2+
// modify, sell and distribute this software is granted provided this
3+
// copyright notice appears in all copies. This software is provided
4+
// "as is" without express or implied warranty, and with no claim as
5+
// to its suitability for any purpose.
6+
#ifndef IMPLICIT_DWA2002325_HPP
7+
# define IMPLICIT_DWA2002325_HPP
8+
# include <boost/type.hpp>
9+
# include <boost/python/converter/implicit.hpp>
10+
# include <boost/python/converter/registry.hpp>
11+
# include <boost/python/converter/type_id.hpp>
12+
13+
namespace boost { namespace python {
14+
15+
template <class Source, class Target>
16+
void implicitly_convertible(boost::type<Source>* = 0, boost::type<Target>* = 0)
17+
{
18+
typedef converter::implicit<Source,Target> functions;
19+
20+
converter::registry::insert(
21+
&functions::convertible
22+
, &functions::construct
23+
, converter::undecorated_type_id<Target>());
24+
}
25+
26+
}} // namespace boost::python
27+
28+
#endif // IMPLICIT_DWA2002325_HPP

include/boost/python/type_from_python.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace detail
2222
}
2323

2424
// A function generator whose static execute() function is an lvalue
25-
// from_python converter using the given Extractor. U is exepcted to
25+
// from_python converter using the given Extractor. U is expected to
2626
// be the actual type of the PyObject instance from which the result
2727
// is being extracted.
2828
template <class Extractor, class U>

src/converter/from_python.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,18 @@ BOOST_PYTHON_DECL rvalue_stage1_data find(
2929
return data;
3030
}
3131

32+
BOOST_PYTHON_DECL rvalue_from_python_registration const* find_chain(
33+
PyObject* source
34+
, rvalue_from_python_registration const* chain)
35+
{
36+
for (;chain != 0; chain = chain->next)
37+
{
38+
if (chain->convertible(source))
39+
break;
40+
}
41+
return chain;
42+
}
43+
3244
BOOST_PYTHON_DECL void* find(
3345
PyObject* source
3446
, lvalue_from_python_registration const* chain)

test/Jamfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ bpl-test test_pointer_adoption ;
5757
bpl-test callbacks ;
5858
bpl-test virtual_functions ;
5959
bpl-test back_reference ;
60+
bpl-test implicit ;
6061

6162
# --- unit tests of library components ---
6263
unit-test indirect_traits_test

test/implicit.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright David Abrahams 2002. Permission to copy, use,
2+
// modify, sell and distribute this software is granted provided this
3+
// copyright notice appears in all copies. This software is provided
4+
// "as is" without express or implied warranty, and with no claim as
5+
// to its suitability for any purpose.
6+
#include <boost/python/class.hpp>
7+
#include <boost/python/implicit.hpp>
8+
#include <boost/python/module.hpp>
9+
#include "test_class.hpp"
10+
11+
// This test shows that a class can be wrapped "as itself" but also
12+
// acquire a back-reference iff has_back_reference<> is appropriately
13+
// specialized.
14+
using namespace boost::python;
15+
16+
typedef test_class<> X;
17+
18+
int x_value(X const& x)
19+
{
20+
return x.value();
21+
}
22+
23+
BOOST_PYTHON_MODULE_INIT(implicit_ext)
24+
{
25+
implicitly_convertible<int,X>();
26+
module("implicit_ext")
27+
.def("x_value", x_value)
28+
.add(
29+
class_<X>("X")
30+
.def_init(args<int>())
31+
.def("value", &X::value)
32+
.def("set", &X::set)
33+
)
34+
;
35+
}
36+
37+
#include "module_tail.cpp"

test/implicit.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
'''
2+
>>> from implicit_ext import *
3+
>>> x_value(X(42))
4+
42
5+
>>> x_value(42)
6+
42
7+
'''
8+
9+
def run(args = None):
10+
import sys
11+
import doctest
12+
13+
if args is not None:
14+
sys.argv = args
15+
return doctest.testmod(sys.modules.get(__name__))
16+
17+
if __name__ == '__main__':
18+
print "running..."
19+
import sys
20+
sys.exit(run()[0])

test/test_class.hpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright David Abrahams 2002. Permission to copy, use,
2+
// modify, sell and distribute this software is granted provided this
3+
// copyright notice appears in all copies. This software is provided
4+
// "as is" without express or implied warranty, and with no claim as
5+
// to its suitability for any purpose.
6+
#ifndef TEST_CLASS_DWA2002326_HPP
7+
# define TEST_CLASS_DWA2002326_HPP
8+
# include <cassert>
9+
10+
template <int n = 0>
11+
struct test_class
12+
{
13+
explicit test_class(int x) : x(x), magic(7654321 + n) { ++counter; }
14+
test_class(test_class const& rhs) : x(rhs.x), magic(7654321 + n) { ++counter; }
15+
virtual ~test_class() { assert(magic == 7654321 + n); magic = 6666666; x = 9999; --counter; }
16+
17+
void set(int x) { assert(magic == 7654321 + n); this->x = x; }
18+
int value() const { assert(magic == 7654321 + n); return x; }
19+
static int count() { return counter; }
20+
private:
21+
void operator=(test_class const&);
22+
private:
23+
int x;
24+
long magic;
25+
static int counter;
26+
};
27+
28+
template <int n>
29+
int test_class<n>::counter;
30+
31+
#endif // TEST_CLASS_DWA2002326_HPP

0 commit comments

Comments
 (0)