Re: [C++-sig] problem chaning object state using a python class that inherits from c++ class
David, Here's a simpler version: struct Data { int a; }; class B { public: virtual void Update(Data& a) = 0; ~B() {} }; class D : public B { virtual void Update(Data& a) { a.a = 10; } }; class C { public: void SetBptr(B* newB) { Bptr = newB; } void Update() { // this doesn't seem to work correctly if Bptr is a python object Bptr->Update(d); } int GetData_a() const { return d.a; } private: Data d; B* Bptr; }; here is the generated code from pyste: // Boost Includes ============================================================== #include <boost/python.hpp> #include <boost/cstdint.hpp> // Includes ==================================================================== #include "test.h" // Using ======================================================================= using namespace boost::python; // Declarations ================================================================ namespace { struct B_Wrapper: B { B_Wrapper(PyObject* py_self_, const B& p0): B(p0), py_self(py_self_) {} B_Wrapper(PyObject* py_self_): B(), py_self(py_self_) {} void Update(Data& p0) { call_method< void >(py_self, "Update", p0); } PyObject* py_self; }; }// namespace // Module ====================================================================== BOOST_PYTHON_MODULE(PysteError) { class_< Data >("Data", init< >()) .def(init< const Data& >()) .def_readwrite("a", &Data::a) ; scope* B_scope = new scope( class_< B, boost::noncopyable, B_Wrapper >("B", init< >()) .def("Update", pure_virtual(&B::Update)) ); register_ptr_to_python< boost::shared_ptr< B >
(); delete B_scope;
class_< C >("C", init< >()) .def(init< const C& >()) .def("SetBptr", &C::SetBptr, with_custodian_and_ward< 1, 2 >()) .def("Update", &C::Update) .def("GetData_a", &C::GetData_a) ; class_< D, bases< B > >("D", init< >()) .def(init< const D& >()) ; } Here is the test code: Expected 10 (good)
from PysteError import * c = C() d = D() c.SetBptr(d) c.Update() print c.GetData_a() 10
Expected -1 (bad)
class E(B): ... def Update(self,data): ... data.a = -1 ... e = E() cc = C() cc.SetBptr(e) cc.Update() print cc.GetData_a() 0
Expected -1 (good)
data = Data() e.Update(data) print data.a -1
Hope this exposes the problem better. I honestly don't have any idea why this doesn't work. Not even a clue where to start looking for a bug. Alexis Programming Tutorial: In Python: To do this, do this In Perl: To do this, do this or this or this or this... In C: To do this, do this, but be careful In C++: To do this, do this, but don't do this, be careful of this, watch out for this, and whatever you do, don't do this __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
"Alexis H. Rivera-Rios" <ahrivera@yahoo.com> writes:
David,
Here's a simpler version:
Thanks. In this case the problem is very simple:
namespace {
struct B_Wrapper: B { B_Wrapper(PyObject* py_self_, const B& p0): B(p0), py_self(py_self_) {}
B_Wrapper(PyObject* py_self_): B(), py_self(py_self_) {}
void Update(Data& p0) { call_method< void >(py_self, "Update", p0); ^^
Here, p0 is passed by value. If you want it to be passed by reference you need to pass boost::ref(p0) instead. Pyste is doing a couple of insane things here, neither of which contributes to your problem: 1. It's using old-style polymorphism support instead of the facilities of boost/python/wrapper.hpp and...
}
PyObject* py_self; };
}// namespace
// Module ====================================================================== BOOST_PYTHON_MODULE(PysteError) { class_< Data >("Data", init< >()) .def(init< const Data& >()) .def_readwrite("a", &Data::a) ;
scope* B_scope = new scope(
... 2. This! I was very surprised to see it. There's no need for a scope here to begin with, and scopes should almost never be allocated dynamically! { scope B_scope = class_< B, boost::noncopyable, B_Wrapper >("B", init< >()) .def("Update", pure_virtual(&B::Update)); register_ptr_to_python< boost::shared_ptr< B > >(); } would have been more appropriate *if* a scope were needed. But it isn't! HTH, -- Dave Abrahams Boost Consulting www.boost-consulting.com
participants (2)
-
Alexis H. Rivera-Rios -
David Abrahams