A boost::python problem
*I abstract the problem below:*
t1.cpp:
#include
I can at least explain why the problem occurs, but I'm not sure if I can
suggest a solution at this time.
The problem is that inside X::test there are two separate shared_ptr
instances pointing to the same A object. One has been created in main(), and
another has been created by Boost.Python for the x.test( a ) call in t1.py.
It so happens that the current behavior of enable_shared_from_this is for
the second instance to override the first one; that is, _internal_weak_this
is reinitialized from the 'pObj' argument when it's created.
Once 'pObj' goes out of scope, the weak_ptr expires, and shared_from_this
starts throwing bad_weak_ptr.
By using a raw pointer argument, you avoid this reinitialization.
We've been thinking of changing the behavior of enable_shared_from_this in
such cases, making it ignore subsequent shared_ptr instances to the same
object and having it stick to the first one. This, however, will not happen
for the upcoming 1.36 release of Boost.
You can in principle achieve the same result by patching your local copy of
Boost to make weak_ptr::_internal_assign only initialize when
this->expired() is true, but this has never been tested.
----- Original Message -----
From: "lxcypp lxc"
To:
*I abstract the problem below:*
t1.cpp:
#include
#include #include #include <iostream> #include <string> #include <list> using namespace std; using namespace boost::python; static object mainobj, global;
class A : public boost::enable_shared_from_this<A> { public: void test(); };
class X { public: void test(boost::shared_ptr<A> pObj){} };
typedef boost::shared_ptr < A > A_ptr; typedef boost::shared_ptr < X > X_ptr;
X_ptr xx;
void A::test() { object aa = global[ "aa" ]; A_ptr pa( shared_from_this() ); aa( xx, pa ); }
BOOST_PYTHON_MODULE(pythonobject) { class_ <A>("A") .def("test", &A::test) ;
class_ <X>("X") .def("test", &X::test) ;
register_ptr_to_python
(); register_ptr_to_python (); } int main() { Py_Initialize();
initpythonobject(); PyRun_SimpleString("import pythonobject"); mainobj = import("__main__"); global=(mainobj.attr("__dict__"));
A_ptr a( new A ); X_ptr x( new X ); xx = x;
try { exec_file("t1.py", global, global);
a->test(); a->test(); a->test(); } catch (error_already_set) { PyErr_Print(); }
return 0; }
t1.py:
#!/usr/bin/python #coding:utf-8 def aa(x,a): x.test( a ) return 1
*after execute t1.cpp , I got this erro info:
terminate called after throwing an instance of 'boost::bad_weak_ptr' what(): tr1::bad_weak_ptr
When debug the program, I found after first "a->test()" call, a._internal_weak_this.use_count became 0. It's obviously wrong... so the after "a->test()" will cause error.
But if change void test(boost::shared_ptr<A> pObj){} to void test(A* pObj){}
I got no error. The errror is gone. Will someone explain this prolbem to me? Thank you.*
Thank you for your replay.
You mean:
when Python call C++ function , it will pass a RAW pointer (NOT a
shared_ptr) to C++, and when pointer implict convert to a shared_ptr<T>, we
got a totally different shared_ptr to the pointer, so that the
_internal_weak_this will be reinitialized .
Is that right?
2008/8/4 Peter Dimov
I can at least explain why the problem occurs, but I'm not sure if I can suggest a solution at this time.
The problem is that inside X::test there are two separate shared_ptr instances pointing to the same A object. One has been created in main(), and another has been created by Boost.Python for the x.test( a ) call in t1.py.
It so happens that the current behavior of enable_shared_from_this is for the second instance to override the first one; that is, _internal_weak_this is reinitialized from the 'pObj' argument when it's created.
Once 'pObj' goes out of scope, the weak_ptr expires, and shared_from_this starts throwing bad_weak_ptr.
By using a raw pointer argument, you avoid this reinitialization.
We've been thinking of changing the behavior of enable_shared_from_this in such cases, making it ignore subsequent shared_ptr instances to the same object and having it stick to the first one. This, however, will not happen for the upcoming 1.36 release of Boost.
You can in principle achieve the same result by patching your local copy of Boost to make weak_ptr::_internal_assign only initialize when this->expired() is true, but this has never been tested.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
lxcypp lxc:
Thank you for your replay.
You mean: when Python call C++ function , it will pass a RAW pointer (NOT a shared_ptr) to C++, and when pointer implict convert to a shared_ptr<T>, we got a totally different shared_ptr to the pointer, so that the _internal_weak_this will be reinitialized .
Is that right?
Not exactly, but the end result is the same. Python does pass a raw pointer (PyObject*) to the Boost.Python translation layer. Boost.Python then constructs a specially crafted shared_ptr<A> from that. There is no implicit conversion from T* to shared_ptr<T>.
Thank you. I understand that.
ps: It's my mis-express that the implicit conversion from T* to
shared_ptr<T>.
I mean that Boost.Python constructs a shared_ptr<T> by it's construction
method with a raw pointer .
2008/8/5 Peter Dimov
Not exactly, but the end result is the same. Python does pass a raw pointer (PyObject*) to the Boost.Python translation layer. Boost.Python then constructs a specially crafted shared_ptr<A> from that. There is no implicit conversion from T* to shared_ptr<T>. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (2)
-
lxcypp lxc
-
Peter Dimov