[C++-sig] pybindgen: Why does pybindgen want to call constructors for a singleton class?

Gustavo Carneiro gjcarneiro at gmail.com
Tue Jun 23 02:11:14 CEST 2009


2009/6/22 J. Michael Owen <mikeowen at llnl.gov>

> I'm looking at wrapping a C++ singleton with pybindgen, and it seems that
> if I expose the method for getting the instance to python the generated code
> wants to call a copy constructor, which seems wrong to me.  If for instance
> I define a class "A" as a singleton:
>
> class A {
> public:
>  static A* instancePtr() {
>    if (A::mInstancePtr == 0) A::mInstancePtr = new A;
>    return mInstancePtr;
>  }
> private:
>  A();
>  A(const A& rhs);
>  A& operator=(const A& rhs);
>  static A* mInstancePtr;
> };
>
> and I wrap A and its instance method like so:
>
> mod = Module("singleton_example")
> mod.add_include('"singleton_example.hh"')
> x = mod.add_class("A", is_singleton=True)
> x.add_method("instancePtr", retval("A*", caller_owns_return=False), [])
>
> pybindgen generates the following code for the instancePtr method:
>
> PyObject *
> _wrap_PyA_instancePtr(PyA *self)
> {
>    PyObject *py_retval;
>    A *retval;
>    PyA *py_A;
>
>    retval = self->obj->instancePtr();
>    if (!(retval)) {
>        Py_INCREF(Py_None);
>        return Py_None;
>    }
>    py_A = PyObject_New(PyA, &PyA_Type);
>    py_A->obj = new A(*retval);
>    py_retval = Py_BuildValue((char *) "N", py_A);
>    return py_retval;
> }
>
> As you can see it is trying to construct a new object with a copy of the A
> retval parameter (the line that reads "py_A->obj = new A(*retval);".  This
> is of course forbidden because all of A's constructors are private -- as a
> singleton we don't want anyone calling constructors on this object.
>  Moreover, since I exposed "instancePtr" as returning a pointer I did not
> expect any copies to be generated anyway -- I'd like to see the pointer
> "retval" sent back directly (even if this wasn't a singleton).  Am I missing
> some syntax here to prevent pybindgen from trying to make these copies?


It tries to copy because you say caller_owns_return=False, pybindgen needs
to copy the object so that the wrapper can own the object.  What you can do
here is use caller_owns_return=True instead of False.  It's OK in this case;
because of the is_singleton option, the C++ wrapped object will never be
freed when the wrapper is destroyed.

-- 
Gustavo J. A. M. Carneiro
INESC Porto, Telecommunications and Multimedia Unit
"The universe is always one step beyond logic." -- Frank Herbert
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20090623/9f4092bb/attachment.htm>


More information about the Cplusplus-sig mailing list