List Info

Thread: c++ to python object conversion problem




c++ to python object conversion problem
country flaguser name
Austria
2007-03-03 13:05:25
hi all,

i've wrapped a simple c++ class with boost python, which
looks like
this:

class simple: boost::noncopyable{};

an instance of this class (or a derived one) is allocated
from python
and a pointer is stored in a class with a virtual function:

class callback: boost::noncopyable
{
   virtual void overloadme(simple const &) = 0
   void run(void) { this->overloadme(s_); }	
   void set(simple * s) {s_ = s;}
   simple * s_;
};

this callback class is wrapped like it's described in the
tutorial:

class cbwrapper: callback, wrapper<callback>
{
   virtual void overloadme(simple const & s) {
       this->get_override("overloadme")(s);
   }
};

callback::run is called from the c++ code later in the
program
asynchronously. however, when trying to call the overridden
function,
the program crashes:

>  0 PyErr_Restore    PC=0xb7f30a9f, FP=0xb45461c8
[/usr/lib/libpython2.4.so.1.0]
   1 PyErr_SetObject  PC=0xb7f30b30, FP=0xb45461c8
[/usr/lib/libpython2.4.so.1.0]
   2
_ZNK5boost6python9converter12registration9to_pythonEPVKv
PC=0xb519c4d6, FP=0xb45461c8
[/usr/lib/libboost_python-mt.so.1.33.1]
   3
_ZN5boost6python9converter6detail18arg_to_python_baseC2EPVKv
RKNS1_12registrationE PC=0xb51accdf, FP=0xb45461e8
[/usr/lib/libboost_python-mt.so.1.33.1]
   4
boost::python::converter::detail::value_arg_to_python<sim
ple>::not-in-charge value_arg_to_python PC=0xb678648b,
FP=0xb4546208
[/usr/include/boost/python/converter/arg_to_python.hpp#209]
   5
boost::python::converter::arg_to_python<simple>::arg_t
o_python PC=0xb67864b5, FP=0xb4546228
[/usr/include/boost/python/converter/arg_to_python.hpp#256]
   6 boost::python::override::operator ()<simple>
PC=0xb67864e0, FP=0xb4546268
[/usr/include/boost/python/override.hpp#138]


the instance of the wrapped object is still valid, but the
conversion
from the c++ object to the python object seems to be the
reason of the
crash ...

any idea, what i am missing?

thanks, tim

--
timklingt.org    ICQ: 96771783
http://tim.klingt.org

Just what the hell is the experimental tradition?
  Morton Feldman

_______________________________________________
C++-sig mailing list
C++-sigpython.org
http:
//mail.python.org/mailman/listinfo/c++-sig

Re: c++ to python object conversion problem
user name
2007-03-03 13:21:25
On 3/3/07, Tim Blechmann <timklingt.org> wrote:
> hi all,
>
> i've wrapped a simple c++ class with boost python,
which looks like
> this:
>
> class simple: boost::noncopyable{};
>
> an instance of this class (or a derived one) is
allocated from python
> and a pointer is stored in a class with a virtual
function:
>
> class callback: boost::noncopyable
> {
>    virtual void overloadme(simple const &) = 0
>    void run(void) { this->overloadme(s_); }
>    void set(simple * s) {s_ = s;}
>    simple * s_;
> };
>
> this callback class is wrapped like it's described in
the tutorial:
>
> class cbwrapper: callback, wrapper<callback>
> {
>    virtual void overloadme(simple const & s) {
>       
this->get_override("overloadme")(s);

I think that the problem in this line. By default
Boost.Python pass copy of the
object to the "override" function. In this case
"simple" is noncopyable.
( I don't understand why you didn't get compile time error
).
In my opinion you should change
    this->get_override("...")(s)
to
    this->get_override( ... )( boost::ref(s) )

P.S. Also you didn't specified how you exposed the classes
to Python.

P.S. Py++ is aware of this and would generate the right from
the beginning

-- 
Roman Yakovenko
C++ Python language binding
http://www.language-
binding.net/
_______________________________________________
C++-sig mailing list
C++-sigpython.org
http:
//mail.python.org/mailman/listinfo/c++-sig

Re: c++ to python object conversion problem
country flaguser name
Austria
2007-03-04 07:37:01
hi roman ... thanks for your hint

i've added the wrapper code below the classes:

> > class simple: boost::noncopyable{};

class_<simple,
boost::noncopyable>("simple");

> > an instance of this class (or a derived one) is
allocated from python
> > and a pointer is stored in a class with a virtual
function:
> >
> > class callback: boost::noncopyable
> > {
> >    virtual void overloadme(simple const &) =
0
> >    void run(void) { this->overloadme(s_); }
> >    void set(simple * s) {s_ = s;}
> >    simple * s_;
> > };
> >
> > this callback class is wrapped like it's described
in the tutorial:
> >
> > class cbwrapper: callback,
wrapper<callback>
> > {
> >    virtual void overloadme(simple const & s)
{
> >       
this->get_override("overloadme")(s);

class_<cbwrapper,
boost::noncopyable>("callback")
    .def("set",  &cbwrapper::set)
    .def("overloadme",
&cbwrapper::overloadme)
    ;

> I think that the problem in this line. By default
Boost.Python pass copy of the
> object to the "override" function. In this
case "simple" is noncopyable.
> ( I don't understand why you didn't get compile time
error ).
> In my opinion you should change
>     this->get_override("...")(s)
> to
>     this->get_override( ... )( boost::ref(s) )

i tried this ... however python is crashing now:

>  0 PyFrame_New      PC=0xb7e2c81a, FP=0xb44aee68
[/usr/lib/libpython2.4.so.1.0]
   1 PyEval_EvalCodeEx PC=0xb7e79b74, FP=0xb44aeee8
[/usr/lib/libpython2.4.so.1.0]
   2 PyClassMethod_New PC=0xb7e2d81d, FP=0xb44aef48
[/usr/lib/libpython2.4.so.1.0]
   3 PyObject_Call    PC=0xb7e14a35, FP=0xb44aef68
[/usr/lib/libpython2.4.so.1.0]
   4 PyClass_IsSubclass PC=0xb7e1b05d, FP=0xb44af1b8
[/usr/lib/libpython2.4.so.1.0]
   5 PyObject_Call    PC=0xb7e14a35, FP=0xb44af1d8
[/usr/lib/libpython2.4.so.1.0]
   6 PyEval_CallObjectWithKeywords PC=0xb7e73d26,
FP=0xb44af1f8 [/usr/lib/libpython2.4.so.1.0]
   7 PyEval_CallFunction PC=0xb7e94207, FP=0xb44af228
[/usr/lib/libpython2.4.so.1.0]
   8 boost::python::override::operator
()<boost::reference_wrapper<const simple> >
PC=0xb66f0712, FP=0xb44af268
[/usr/include/boost/python/override.hpp#138]

> P.S. Py++ is aware of this and would generate the right
from the beginning

... unfortunately, gccxml doesn't like my c++ code :/

any other hints or workarounds? 

thanks ... tim

--
timklingt.org    ICQ: 96771783
http://tim.klingt.org

A paranoid is a man who knows a little of what's going on.
  William S. Burroughs

_______________________________________________
C++-sig mailing list
C++-sigpython.org
http:
//mail.python.org/mailman/listinfo/c++-sig

Re: c++ to python object conversion problem
user name
2007-03-04 08:21:29
On 3/4/07, Tim Blechmann <timklingt.org> wrote:
> hi roman ... thanks for your hint
>
> i've added the wrapper code below the classes:
>
> > > class simple: boost::noncopyable{};
>
> class_<simple,
boost::noncopyable>("simple");
>
> > > an instance of this class (or a derived one)
is allocated from python
> > > and a pointer is stored in a class with a
virtual function:
> > >
> > > class callback: boost::noncopyable
> > > {
> > >    virtual void overloadme(simple const
&) = 0
> > >    void run(void) { this->overloadme(s_);
}
> > >    void set(simple * s) {s_ = s;}
> > >    simple * s_;
> > > };
> > >
> > > this callback class is wrapped like it's
described in the tutorial:
> > >
> > > class cbwrapper: callback,
wrapper<callback>
> > > {
> > >    virtual void overloadme(simple const &
s) {
> > >       
this->get_override("overloadme")(s);
>
> class_<cbwrapper,
boost::noncopyable>("callback")
>     .def("set",  &cbwrapper::set)

A problem could also be here, you have to set call
policies:
http://boost.org/li
bs/python/doc/tutorial/doc/html/python/functions.html#python
.call_policies

Also, creating small and **complete** is much better way to
get help.

-- 
Roman Yakovenko
C++ Python language binding
http://www.language-
binding.net/
_______________________________________________
C++-sig mailing list
C++-sigpython.org
http:
//mail.python.org/mailman/listinfo/c++-sig

Re: c++ to python object conversion problem
country flaguser name
Austria
2007-03-04 08:48:25
hi roman,

i just figured out, that it was a simple python threading
issue, because
the c++ thread hasn't been synchronized with python.
after guarding the calls to the override object by a
PyGILState_Ensure()/Release() pair, it works flawless!

cheers ... tim

On Sun, 2007-03-04 at 16:21 +0200, Roman Yakovenko wrote:
> On 3/4/07, Tim Blechmann <timklingt.org> wrote:
> > hi roman ... thanks for your hint
> >
> > i've added the wrapper code below the classes:
> >
> > > > class simple: boost::noncopyable{};
> >
> > class_<simple,
boost::noncopyable>("simple");
> >
> > > > an instance of this class (or a derived
one) is allocated from python
> > > > and a pointer is stored in a class with
a virtual function:
> > > >
> > > > class callback: boost::noncopyable
> > > > {
> > > >    virtual void overloadme(simple const
&) = 0
> > > >    void run(void) {
this->overloadme(s_); }
> > > >    void set(simple * s) {s_ = s;}
> > > >    simple * s_;
> > > > };
> > > >
> > > > this callback class is wrapped like it's
described in the tutorial:
> > > >
> > > > class cbwrapper: callback,
wrapper<callback>
> > > > {
> > > >    virtual void overloadme(simple const
& s) {
> > > >       
this->get_override("overloadme")(s);
> >
> > class_<cbwrapper,
boost::noncopyable>("callback")
> >     .def("set",  &cbwrapper::set)
> 
> A problem could also be here, you have to set call
policies:
> http://boost.org/li
bs/python/doc/tutorial/doc/html/python/functions.html#python
.call_policies
> 
> Also, creating small and **complete** is much better
way to get help.
> 
--
timklingt.org    ICQ: 96771783
http://tim.klingt.org

Life is really simple, but we insist on making it
complicated.
  Confucius

_______________________________________________
C++-sig mailing list
C++-sigpython.org
http:
//mail.python.org/mailman/listinfo/c++-sig

yet another conversion problem (was: Re: c++ to python object conversion problem)
country flaguser name
Austria
2007-03-04 11:50:04
ok ... now i'm facing the problem, that a class derived from
a c++ class
is converted to the c++ base class, in a python callback:

the c++ classes are:
    struct simple: boost::noncopyable
    {
    };

    struct holder: boost::noncopyable
    {
        simple * s_;
        void set(simple * s)
        {
            s_ = s;
        }

        void run(void)
        {
            this->ping(s_);
        }

        virtual void ping(simple * s) = 0;
    };

    struct holder_wrapper:
        holder,
        wrapper<holder>
    {
        virtual void ping(simple * s)
        {
           
this->get_override("ping")(boost::ref(s));
        }
    };

which are wrapped:
        class_<simple,
boost::noncopyable>("simple");

        class_<holder_wrapper,
boost::noncopyable>("holder")
            .def("set", &holder_wrapper::set)
            .def("run", &holder_wrapper::run)
            .def("ping",
pure_virtual(&holder_wrapper::ping))
            ;

from python, i derive new classes and implement the virtual
function
holder::ping:

class simple_d(simple):
    def __init__(self, i):
        simple.__init__(self)
        self.i = i

class holder_d(holder):
    def __init__(self):
        holder.__init__(self)
    
    def ping(self, s):
        assert(isinstance(s, simple))
        assert(isinstance(s, simple_d))
        print s.i

when i call it like this the instant s in the python code,
the second
assert statement fails. the object is not handled as
simple_d, but as
simple:

s = simple_d(53)
h = holder_d()

h.set(s)
h.run()

is there any way to "upcast" the instance s from
simple to simple_d?


thanks again!

tim

--
timklingt.org    ICQ: 96771783
http://tim.klingt.org

Linux is like a wigwam: no windows, no gates, apache inside,
stable.

_______________________________________________
C++-sig mailing list
C++-sigpython.org
http:
//mail.python.org/mailman/listinfo/c++-sig

[1-6]

about | contact  Other archives ( Real Estate discussion Medical topics )