[C++-sig] Re: Re: How to use call?

Dave Hawkes daveh at cadlink.com
Sat Jun 15 04:49:52 CEST 2002


"David Abrahams" <david.abrahams at rcn.com> wrote in message
news:09e401c213df$33ce2d60$6601a8c0 at boostconsulting.com...
> What comment about MSVC?
>

I'm sure I saw a comment in the source a while back, but I can't find it
now...

> > > > I know the intention here is to copy the lvalue
> > >
> > > Huh? Which lvalue?
> > >
> >
> > The lvalue_from_python code that seems to get invoked
>
> There is no intention to copy an lvalue unless the explicit template
> argument to call<> is a non-pointer, non-reference type.
>

OK


> > > MyClass* p = call<MyClass*>(callable, arg1, arg2, ...);
> > >
> >
> > Then I  will get the "Attempt to return dangling internal reference"
> > exception because I need to take possesion of the returned object.
>
> Well, yeah. Who else is going to keep it alive?
>

Yes, I know, that's my problem.

> >
> > see above, the returned object needs to be 'owned'.
>
> OK, you need what I mentioned to Dominic in a previous message: a smart
> pointer type which holds a PyObject* and which "points to" its contained
> lvalue. Yeah, that's not implemented, but patches are welcome.
>

Well here's my 'quick fix'. It is not feature complete, but if your
interested in something along these lines I can complete it:

namespace boost { namespace python {

template<class T>
struct class_handle {
    class_handle() : class_ptr(NULL) {}
    class_handle(PyObject* p) : h(p) { init(p); }
    class_handle(handle<> h) : h(h) { init(h.get()); }
    T* operator->() const { return class_ptr; }
    T* get() const { return class_ptr; }
private:
    void init(PyObject* p)
    {
        class_ptr = reinterpret_cast<T*>(objects::find_instance_impl(p,
type_id<T>()));
        if(!class_ptr) {
            PyErr_SetString(
                PyExc_ReferenceError
                , const_cast<char*>("attempt to find a class pointer from a
non class object"));
            throw_error_already_set();
        }
    }
    handle<> h;
    T* class_ptr;
};

namespace converter {

template<>
struct return_from_python<handle<> > {
    typedef handle<> result_type;
    handle<> operator()(PyObject* p) const { return handle<>(p); }
};

}

}}

After putting this in an appropriate header(?) we can do:

        class_handle<MyClass> pClass(call<handle<> >(pPyClass));
        std::string msg = pClass->func();

There's some small issues such as should the class throw an exception or
just provide a NULL pointer. Also should I use a more generic way of
converting from python, but then class_handle would valid for more than just
our own classes?

Dave Hawkes











More information about the Cplusplus-sig mailing list