[C++-sig] python override of C++ virtual mem fun not exactly working yet

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

[C++-sig] python override of C++ virtual mem fun not exactly working yet

DRandallTaylor
Hello again.  n00b here.
Simple problem, but hard for me, cause I'm n00b.

My Python class derives from a C++ class and overrides a virtual mem fun that
has an implementation.  In the derived Python class, I need "self" to be
treated polymorphically with respect to the C++ base class.  The boost::python
Tutorial gives a sample but the derivation shown of BaseWrap is private, not
public derivation:  "struct BaseWrap : Base, wrapper<Base>".  I know this is a
simple problem... but having trouble with it...

My error msg tells me that my 2nd arg is a InboxListener not a Callback.


  File "test.py", line 9, in __init__
    self.inbox = sess.CreateInbox(self)
ArgumentError: Python argument types in
    Session.CreateInbox(Session, InboxListener)
did not match C++ signature:
    CreateInbox(class Session {lvalue}, class Callback {lvalue})


My C++ stuff:


class CallbackWrap : public Callback, python::wrapper<Callback>
{  public:
    void OnData() // iff public derivation used, then this is virtual; else
non-virtual
    {
        if (python::override the_override = this->get_override("OnData"))
            the_override();
        else  Callback::OnData();
    }
    void default_OnData() { this->Callback::OnData(); }    
};


python::class_ < CallbackWrap, boost::noncopyable > ("Callback")
.def("OnData", &Callback::OnData, &CallbackWrap::default_OnData);


python::class_<Session>("Session")
.def("CreateInbox", &Session::CreateInbox, python::return_value_policy<
python::return_by_value >());


And my Python stuff:


class InboxListener(Callback):
        def __init__(self, session):
                self.inbox = session.CreateInbox(self)
        def OnData():
                print "OnData called"
                return


Seems like "self" passed to  session.CreateInbox should be treated as a
Callback type, since I've used public derivatation.  Can you help me spot the
error of my ways?  And I thank you!

DRandallTaylor









_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig
Reply | Threaded
Open this post in threaded view
|

Re: [C++-sig] python override of C++ virtual mem fun not exactly working yet

Stefan Seefeld
DRandallTaylor wrote:
> Hello again.  n00b here.
> Simple problem, but hard for me, cause I'm n00b.
>
> My Python class derives from a C++ class and overrides a virtual mem fun that
> has an implementation.  In the derived Python class, I need "self" to be
> treated polymorphically with respect to the C++ base class.  The boost::python
> Tutorial gives a sample but the derivation shown of BaseWrap is private, not
> public derivation:  "struct BaseWrap : Base, wrapper<Base>".  I know this is a
> simple problem... but having trouble with it...

No it isn't. The default access-specifier for struct is public, not private.


>
> My error msg tells me that my 2nd arg is a InboxListener not a Callback.
>
>
>   File "test.py", line 9, in __init__
>     self.inbox = sess.CreateInbox(self)
> ArgumentError: Python argument types in
>     Session.CreateInbox(Session, InboxListener)
> did not match C++ signature:
>     CreateInbox(class Session {lvalue}, class Callback {lvalue})

[...]


> And my Python stuff:
>
>
> class InboxListener(Callback):
> def __init__(self, session):
> self.inbox = session.CreateInbox(self)

In python you have to invoke the base class constructor explicitely in order
to initialize it. I believe this will fix your problem.

HTH,
                Stefan
_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig
Reply | Threaded
Open this post in threaded view
|

Re: [C++-sig] python override of C++ virtual mem fun not exactly working yet

DRandallTaylor
I've added the invocation of the base class constructor (thanks Stefan):

class InboxListener(Callback):
        def __init__(self, sess):
                Callback.__init__(self)
                self.inbox = sess.CreateInbox(self)  # ArgumentError here
        def OnData():
                print "OnData called"

But I still get this:


ArgumentError: Python argument types in
    VIAmSession.CreateInbox(Session, InboxListener)
did not match C++ signature:
    CreateInbox(class Session {lvalue}, class Callback {lvalue})


Python does not yet know that my InboxListener is derived from Callback.  How
shall I tell her?

Cheers.






_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig
Reply | Threaded
Open this post in threaded view
|

Re: [C++-sig] python override of C++ virtual mem fun not exactly working yet

DRandallTaylor
DRandallTaylor <DRandallTaylor <at> yahoo.com> writes:

> [...]

May I rephrase?

Is conversion from a Python class to the boost::python type that it is derived
from automatic?  I think it probably is, therefore I must be doing something
wrong:


class InboxListener(VIAmCallback):
        def __init__(self, sess):
                VIAmCallback.__init__(self)
                self.inbox = sess.CreateInbox(self)


gives me:


  File "test.py", line 32, in run
    listener = InboxListener(sess)
  File "test.py", line 10, in __init__
    self.inbox = sess.CreateInbox(self)
ArgumentError: Python argument types in
    VIAmSession.CreateInbox(VIAmSession, InboxListener)
did not match C++ signature:
    CreateInbox(class tt_stream_ns::VIAmSession {lvalue}, class
tt_stream_ns::VIAmCallback {lvalue})



And my C++ looked like this:


struct VIAmCallbackPublic : public tt_stream_ns::VIAmCallback
{
   [...]
};
struct VIAmCallbackWrap : public VIAmCallbackPublic,
python::wrapper<VIAmCallbackPublic>
{
   [...]
]

python::class_ <VIAmCallbackWrap, boost::noncopyable>("VIAmCallback")
        .def("OnData", &VIAmCallbackPublic::OnData,
              &VIAmCallbackWrap::default_OnData);



And I thought that the Python error message above tells me that python does
NOT believe that InboxListener is actually a tt_stream_ns::VIAmCallback.  So I
experimented by added a python::bases<> template template arg like this:


python::class_ <
  VIAmCallbackWrap
  , python::bases<VIAmCallbackPublic, tt_stream_ns::VIAmCallback>
  , boost::noncopyable
> ("VIAmCallback")
def("OnData", &VIAmCallbackPublic::OnData,
    &VIAmCallbackWrap::default_OnData);


And then I get a worse error from Python:


Traceback (most recent call last):
  File "test.py", line 1, in ?
    from pycore import *
RuntimeError: extension class wrapper for base class struct VIAmCallbackPublic
has not been created yet



Am I completely clueless or simply overlooking something.  Please tell me it
is the latter.


Sincerely,
Your Faithful n00b.

DRandallTaylor


_______________________________________________
C++-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/c++-sig