[C++-sig] problem chaning object state using a python class that inherits from c++ class

Alexis H. Rivera-Rios ahrivera at yahoo.com
Wed Aug 17 00:47:49 CEST 2005


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 



More information about the Cplusplus-sig mailing list