2009/6/29 J. Michael Owen <mikeo...@llnl.gov> > Hi Gustavo, > Hmm. I tried this example, but the generated code seems to be still trying > to generate a copy. Here's the example source I'm trying expose: > > #include <iostream> > > class A { > public: > A(const int val): mVal(val) {} > private: > int mVal; > A(); > A(const A& rhs); > A& operator=(const A& rhs); > }; > > class B { > public: > B() {} > virtual ~B() {} > virtual void some_virtual_method(const A& a) const { std::cerr << &a << > std::endl; } > private: > }; > > I try to expose these objects with the following pybindgen code: > > mod = Module("ref_param_example") > mod.add_include('"classes.hh"') > a = mod.add_class("A") > b = mod.add_class("B", allow_subclassing=True) > a.add_constructor([param("int", "val")]) > b.add_constructor([]) > b.add_method("some_virtual_method", None, [Parameter.new("A&", "a", > direction=Parameter.DIRECTION_INOUT)], is_const=True, is_virtual=True) > > Now the generated code contains the following function for the helper class > required since we're allowing subclassing: > > void > PyB__PythonHelper::some_virtual_method(A & a) const > { > PyGILState_STATE __py_gil_state; > B *self_obj_before; > PyObject *py_retval; > PyA *py_A; > > __py_gil_state = (PyEval_ThreadsInitialized() ? PyGILState_Ensure() : > (PyGILState_STATE) 0); > if (!PyObject_HasAttrString(m_pyself, (char *) "_some_virtual_method")) > { > B::some_virtual_method(a); > if (PyEval_ThreadsInitialized()) > PyGILState_Release(__py_gil_state); > return; > } > self_obj_before = reinterpret_cast< PyB* >(m_pyself)->obj; > reinterpret_cast< PyB* >(m_pyself)->obj = const_cast< B* >((const B*) > this); > py_A = PyObject_New(PyA, &PyA_Type); > py_A->obj = &(a); > py_retval = PyObject_CallMethod(m_pyself, (char *) > "_some_virtual_method", (char *) "O", py_A); > if (py_retval == NULL) { > PyErr_Print(); > Py_DECREF(py_A); > reinterpret_cast< PyB* >(m_pyself)->obj = self_obj_before; > if (PyEval_ThreadsInitialized()) > PyGILState_Release(__py_gil_state); > return; > } > if (py_retval != Py_None) { > PyErr_SetString(PyExc_TypeError, "function/method should return > None"); > Py_DECREF(py_retval); > Py_DECREF(py_A); > reinterpret_cast< PyB* >(m_pyself)->obj = self_obj_before; > if (PyEval_ThreadsInitialized()) > PyGILState_Release(__py_gil_state); > return; > } > if (py_A->ob_refcnt == 1) > py_A->obj = NULL; > else{ > > py_A->obj = new A(a); > } > Py_DECREF(py_retval); > Py_DECREF(py_A); > reinterpret_cast< PyB* >(m_pyself)->obj = self_obj_before; > if (PyEval_ThreadsInitialized()) > PyGILState_Release(__py_gil_state); > return; > } > > You can see the line near the end here that is trying to make a copy of the > "a" argument with "py_A->obj = new A(a);", which isn't what we want. Why is > it trying to do that anyway? This was all generated with pybindgen 0.10.0 > by the way -- is there a more recent version that will avoid this problem? >
Ah, right. The thing is, the code tries to make a copy of the object to give to the python wrapper in case it appears the python code kept a reference to the wrapper. I need to fix pybindgen to, if the class has no copy constructor keep the wrapper->obj pointer NULL instead of giving it a copy. The fix has been pushed to the bazaar branch. See https://code.launchpad.net/~gjc/pybindgen/trunk > > Thanks! > > Mike. > > On Jun 28, 2009, at 8:19 AM, Gustavo Carneiro wrote: > > After starting to look at this issue, I realized that this solution is > already implemented actually, but I had forgotten! :P > > You need to tell pybindgen that the reference parameter is INOUT, thus: > > ReferenceManipulator.add_method('do_manipulate_object', 'void', > [Parameter.new('ManipulatedObject&', > 'obj', direction=Parameter.DIRECTION_INOUT)], > is_virtual=True, is_pure_virtual=True) > > Then everything works as expected. I am closing the bug by merely adding a > unit test to cover this problem. Should work in pybindgen 0.10 as well. > > Take care, > > -- > Gustavo J. A. M. Carneiro > INESC Porto, Telecommunications and Multimedia Unit > "The universe is always one step beyond logic." -- Frank Herbert > > > > _______________________________________________ > Cplusplus-sig mailing list > Cplusplus-sig@python.org > http://mail.python.org/mailman/listinfo/cplusplus-sig > -- Gustavo J. A. M. Carneiro INESC Porto, Telecommunications and Multimedia Unit "The universe is always one step beyond logic." -- Frank Herbert
_______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig