[C++-sig] Re: Making copy of function derived from C++ pure virtual function

David Abrahams dave at boost-consulting.com
Mon Dec 13 04:26:21 CET 2004


Paul F. Kunz wrote:
>   This clone function doesn't quite work ...
> 
>       FunctionBase* clone()
>       {
>         PyGILState_STATE state = PyGILState_Ensure ();
>           object py_result;
> 
>            if (override clone = this->get_override("clone"))
>            {
>                 // The Python class author overrode clone; do
>                 // whatever she says
>                 py_result = clone();
>            }
>            else
>            {
>                 object self = get_owner(this);
> 
>                 // Find its most-derived Python class
>                 object my_class = self.attr("__class__");
> 
>                 // call the copy ctor through Python.
>                 py_result = my_class(self);
>            }
>            FunctionWrap* result = extract<FunctionBase*>(py_result);
> 
>            // Make the C++ result control the destiny of the Python result.
>            result->invert_ownership = py_result;
>           PyGILState_Release ( state );
>           return result;
>       }
> 
> This is being called from different thread from the one that created
> the Python object, thus the Ensure/Release methods are used.
> 
> If I implement clone in Python, the the function gets called, but
> calling clone() leads to ...
> 
> terminate called after throwing an instance of
> 'boost::python::error_already_set'

This means some Python exception is being thrown.  You might set a
breakpoint on boost::python::detail::throw_error_already_set (I think I
have the namespace right) and look just up the stack to see what the
actual error being reported is.

> If I do not implement clone in Python, the the other path of the if is
> taken and get same result.   I can call other methods implemented in
> Python without problem.
> 
>    With the debugger, I walked thru lots of Python code and get quite
> deep before it 

"it?"

> decides to return a null pointer instead of a new
> object.   I note that it called, static PyObject *
> instancemethod_call(PyObject *func, PyObject *arg, PyObject *kw)
> Is this correct?   

How should I know?  That function gets used to implement all sorts of
things in Python.

> In C++ an constructor wouldn't be called a instance
> method. 

you are being led astray by terminology

>    Any suggestions on what to look for?

Yes:  Get rid of all the threading stuff and *all* the superfluous
functions/methods (you still had several unused Python methods floating
around in what you posted the last time) and reduce this to a simple
test case that can be used as a proof-of-concept for what you're doing
with cloning.  Test all the cloning cases you want to handle (e.g.
override clone in some Python derived classes but not others).  You will
very quickly narrow the issue down and if you don't discover that you
had a bug in your code, post the result and I will look at it.

-- 
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com




More information about the Cplusplus-sig mailing list