[C++-sig] boost::python and boost::shared_ptr strict weak ordering problem
Markus Woschank
markus.woschank at gmail.com
Fri Aug 1 23:55:51 CEST 2008
Hi list,
I'm getting a strange behaviour with shared_ptr objects as arguments of
wrapped C++ functions.
The problem occurs when i try to use the shared_ptr objects in a
std::set which (AFAIK) uses
strict weak ordering equivalence [ !(a<b) && !(b<a) ]. The problem also
only seems to occur if
there are different calls to C++ from python, while the C++ code holds a
shared_ptr somewhere.
I'm using boost 1.35.0.
Here is a sample program that should demonstrate my problem
C++ code:
---
class Toast : boost::noncopyable
{
public:
typedef boost::shared_ptr<Toast> ptr;
static ptr create()
{ return ptr( new Toast() ); }
private:
Toast() {}
};
bool ptr_equals_last(Toast::ptr p)
{
static Toast::ptr last;
bool equal = !(p<last) && !(last<p);
last = p;
return equal;
}
BOOST_PYTHON_MODULE(ptr_test)
{
using namespace boost::python;
class_< Toast, Toast::ptr, boost::noncopyable >("Toast",no_init)
.def("create",&Toast::create)
.staticmethod("create");
;
def("ptr_equals_last",ptr_equals_last);
}
---
[ also available (for some time) on http://tmp.netst.at/python_module.cpp ]
python test and output:
---
Python 2.5.2 (r252:60911, Aug 1 2008, 22:31:18)
[GCC 4.1.2 (Gentoo 4.1.2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ptr_test import Toast,ptr_equals_last
>>>
>>> t = Toast.create() # instance for testing
>>> t
<ptr_test.Toast object at 0x7f10e95b6578>
>>> ptr_equals_last(None) # should return True ( empty == empty =>
equivalent )
True
>>> ptr_equals_last(None) # should return True ( empty == empty => e. )
True
>>>
>>> ptr_equals_last(t) # should return False ( empty != t => not e. )
False
>>> ptr_equals_last(t) # should return True ( t == t => e. )
False
>>> ptr_equals_last(t) # should return True ( t == t => e. )
False
>>> ptr_equals_last(None) # should return False ( t != empty => not e. )
False
>>> ptr_equals_last(None) # should return True ( empty == empty => e. )
True
---
[ also available (for some time) on http://tmp.netst.at/test.py ]
PS: After debugging a little bit my wild guess is, that boost.python
uses the shared_ptr objects with
custom deleter function that decrements the python refcount. And such
custom shared_ptrs are created
every time a C++ function with an shared_ptr argument is called (while
incrementing the python refcount).
Which seems to work fine but (IMO) breaks the less than operator of
boost::shared_ptr documented at
[http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/shared_ptr.htm#functions]
- but as already said, it's
only a wild guess.
Cheers,
Markus
More information about the Cplusplus-sig
mailing list