[C++-sig] pybindgen: allow_subclassing option causing reference parameters to be copied?

J. Michael Owen mikeowen at llnl.gov
Wed Jun 24 23:34:15 CEST 2009


Hi again,

I've run across another issue confusing me as I try to use pybindgen,  
in this case it's the treatment of reference parameters in virtual  
methods where you're allowing the class to be subclassed from python.   
It looks like the helper class that is generated is making copies of  
parameters that are being passed as references, which is not what we  
want.  Take the following example C++ classes:

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'd like to be able to create subclasses of B from python, so I try  
wrapping these classes 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, [param("A&", "a")],  
is_const=True, is_virtual=True)

The resulting generated code contains the following:

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 = new A(a);
....

As you can see, the last line quoted here is trying to make a copy of  
the instance "a" that was passed in.  In this example this will not  
compile because the copy constructor for A is private.  In general we  
don't want to make copies of reference parameters regardless of course.

Am I once again missing something here?  Is there some way I can  
declare that the passed parameters for "some_virtual_method" should  
really be treated as references and not copied?

Thanks!

Mike.




More information about the Cplusplus-sig mailing list