[C++-sig] weak_ptr to this in C++ classes extended from python
Bryan Catanzaro
bcatanzaro at acm.org
Fri Apr 27 08:22:44 CEST 2012
I think the problem is that aa is no longer an ExtendedA object,
because when you call ptr() it returns a pointer to the base C++ A
class, not the derived class.
I think at this point it's probably best to reconsider the problem and
come up with a simpler solution. Why do you want to expose the ptr
method to Python anyway?
- bryan
On Thu, Apr 26, 2012 at 11:49 AM, Holger Brandsmeier <brandsmeier at gmx.de> wrote:
> Bryan,
>
> my problems happen as soon as I need to use wrappers. I really need
> the class that I extend in python to implement some pure virtual
> function in the C++ class. I extended your code and refined what is
> going wrong. I tried several Variants with different errors, I used
> #defines to show you all 4 versions, next to each Variant I put a C++
> comment of what is going wrong.
>
> So here it is:
>
> ------------ foo.cpp ------------
> #include <boost/python.hpp>
> #include <boost/shared_ptr.hpp>
> #include <boost/enable_shared_from_this.hpp>
> #include <iostream>
>
> using namespace boost::python;
>
> class A
> : public boost::enable_shared_from_this<A> {
> static int counter;
> public:
> int id;
> A() {
> id = counter++;
> std::cout << "Constructing A[" << id << "]" << std::endl;
> }
> ~A() {
> std::cout << "Destructing A[" << id << "]" << std::endl;
> }
> boost::shared_ptr<A> ptr() {
> return shared_from_this();
> }
> #define VARIANT0
> #ifdef VARIANT0
> // this variant works nicely with VARIANT1 below (compiles and
> // no error for `aa = a.ptr()`), but it produces wrong results,
> // i.e. `77` is returned for `aa.foo()` although it should have
> // been `33`.
> virtual int foo() {
> return 77;
> }
> #else
> virtual int foo() = 0;
> #endif
> };
>
> struct AWrapper : public A, public boost::python::wrapper<A> {
> virtual int foo() {
> if( override f = this->get_override("foo") ) {
> return f();
> } else {
> return 42;
> }
> }
> };
>
> int A::counter = 0;
>
> using namespace boost::python;
>
>
> BOOST_PYTHON_MODULE(foo) {
> #define VARIANT1
> //#define VARIANT2
> //#define VARIANT3
>
> #ifdef VARIANT1
> // The following line doesn't compites it gives the error:
> // error: cannot allocate an object of abstract type ‘A’
> class_<AWrapper, boost::shared_ptr<A>, boost::noncopyable >("A", init<>())
> #endif
> #ifdef VARIANT2
> // the following compiles, but produces an error in python, when executing
> // aa = a.ptr();
> // RuntimeError: tr1::bad_weak_ptr
> class_<AWrapper, boost::noncopyable >("A", init<>())
> #endif
> #ifdef VARIANT3
> // the following compiles, but produces an error in python, when executing
> // aa = a.ptr();
> // TypeError: No to_python (by-value) converter found for C++ type:
> boost::shared_ptr<A>
> class_<AWrapper, boost::shared_ptr<AWrapper>, boost::noncopyable
>>("A", init<>())
> #endif
> .def("ptr", &A::ptr)
> .def("foo", &A::foo)
> ;
> }
> -----------------------------------
>
> ------------ foo.py ------------
> import foo
>
> class ExtendedA(foo.A):
> def foo(self):
> return 33;
>
> a0 = foo.A()
> a = ExtendedA()
> aa = a.ptr();
> print a.foo()
> del a
> print aa.foo()
> -----------------------------------
>
> Do you have any suggestion how to get this working?
> -Holger
>
> On Thu, Apr 26, 2012 at 18:43, Bryan Catanzaro <bcatanzaro at acm.org> wrote:
>> Holger Brandsmeier <brandsmeier <at> gmx.de> writes:
>>
>>>
>>> Dear list,
>>>
>>> how is it possible to have a class in C++ that can be extended from
>>> python and that stores a weak_ptr to itself?
>>
>>
>> Have you tried using boost::enable_shared_from_this? The following example code
>> seems to do what you want.
> _______________________________________________
> Cplusplus-sig mailing list
> Cplusplus-sig at python.org
> http://mail.python.org/mailman/listinfo/cplusplus-sig
More information about the Cplusplus-sig
mailing list