Skip to content

Commit 9dfe98a

Browse files
committed
bug fix + regression test
[SVN r17002]
1 parent 399cf70 commit 9dfe98a

File tree

5 files changed

+74
-10
lines changed

5 files changed

+74
-10
lines changed

include/boost/python/converter/return_from_python.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,7 @@ namespace detail
4040
template <class T>
4141
struct return_rvalue_from_python
4242
{
43-
typedef typename mpl::if_<
44-
mpl::logical_and<
45-
has_trivial_copy<T>, mpl::bool_c<(sizeof(T) <= 2 * sizeof(double))>
46-
>
47-
, T
48-
, T&
49-
>::type result_type;
43+
typedef T result_type;
5044

5145
return_rvalue_from_python();
5246
result_type operator()(PyObject*);
@@ -127,6 +121,12 @@ namespace detail
127121
inline typename return_rvalue_from_python<T>::result_type
128122
return_rvalue_from_python<T>::operator()(PyObject* obj)
129123
{
124+
// Take possession of the source object here. If the result is in
125+
// fact going to be a copy of an lvalue embedded in the object,
126+
// and we take possession inside rvalue_result_from_python, it
127+
// will be destroyed too early.
128+
handle<> holder(obj);
129+
130130
return *(T*)
131131
(rvalue_result_from_python)(obj, m_data.stage1);
132132
}

src/converter/from_python.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,6 @@ BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1(
8383
BOOST_PYTHON_DECL void* rvalue_result_from_python(
8484
PyObject* src, rvalue_from_python_stage1_data& data)
8585
{
86-
// Take possession of the source object.
87-
handle<> holder(src);
88-
8986
// Retrieve the registration
9087
// Cast in two steps for less-capable compilers
9188
void const* converters_ = data.convertible;

test/Jamfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ bpl-test back_reference ;
9595
bpl-test implicit ;
9696
bpl-test data_members ;
9797

98+
bpl-test ben_scott1 ;
99+
98100
bpl-test bienstman1 ;
99101
bpl-test bienstman2 ;
100102
bpl-test bienstman3 ;

test/ben_scott1.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include <boost/python.hpp>
2+
#include <iostream>
3+
using namespace boost::python;
4+
using namespace boost;
5+
6+
struct Product {};
7+
typedef shared_ptr<Product> ProductPtr;
8+
9+
10+
struct Creator
11+
{
12+
virtual ~Creator() {}
13+
virtual ProductPtr create() = 0;
14+
};
15+
16+
17+
struct Factory
18+
{
19+
void reg(Creator* c) { mC = c; }
20+
ProductPtr create()
21+
{
22+
std::cout << "Name: " << (typeid(*mC)).name() << std::endl;
23+
return mC->create();
24+
}
25+
26+
private:
27+
Creator* mC;
28+
};
29+
30+
struct CreatorWrap : public Creator
31+
{
32+
CreatorWrap(PyObject* self) : mSelf(self) {}
33+
ProductPtr create() { return call_method<ProductPtr>(mSelf, "create"); }
34+
PyObject* mSelf;
35+
};
36+
37+
BOOST_PYTHON_MODULE(ben_scott1_ext)
38+
{
39+
class_<Product, ProductPtr>("Product");
40+
41+
class_<Creator, CreatorWrap, noncopyable>("Creator")
42+
.def("create", &CreatorWrap::create)
43+
;
44+
45+
class_<Factory>("Factory")
46+
.def("reg", &Factory::reg, with_custodian_and_ward<1,2>())
47+
.def("create", &Factory::create)
48+
;
49+
}
50+
51+
#include "../test/module_tail.cpp"

test/ben_scott1.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# This regression test checks that call_method<T>(...) where T is a
2+
# non-reference, non-pointer type that happens to be held inside the
3+
# result object (and thus is found as an lvalue) works.
4+
from ben_scott1_ext import *
5+
6+
class CreatorImpl(Creator):
7+
def create(self):
8+
return Product()
9+
10+
factory = Factory()
11+
c = CreatorImpl()
12+
factory.reg(c)
13+
14+
a = factory.create()

0 commit comments

Comments
 (0)