Skip to content

Child Class Method Not Being Called as Expected, Base Class Method Called Instead #1552

Closed
@bgoodman44

Description

@bgoodman44

Hello,

I have a simple test case for polymorphism that isn't working quite right.. I have two C++ classes, Client and Dispatcher. Dispatcher has a method called "Dispatch" that takes a Client* as an input, and calls the the clients virtual ProcessEvent() method. I've made both of these classes available to python using the code below. I've derived from the Client class as the python class SomeClient, and overridden its ProcessEvent function. When I call "Dispatch" from anywhere EXCEPT inside the SomeClient::ProcessEvent method, everything works as expected, i get a report from the child class. But when I call Dispatch from within SomeClient::ProcessEvent, the base classes ProcessEvent is called. Any ideas what could be going wrong here? I expect to get an infinite recursion that results in SomeClient::ProcessEvent being called forever.

C++:

#include <iostream>
#include "pybind11/pybind11.h"

namespace py = pybind11;
class Dispatcher;
class Client
{
public:
    Client(Dispatcher* disp): PtrD(disp)
    {
        std::cout << "In Client::Client\n";
    }
    virtual ~Client(){};
    virtual void ProcessEvent()
    {
        std::cout << "THIS SHOULDN'T HAPPEN --In Client::ProcessEvent\n";
    }
    Dispatcher* PtrD;
};
class Dispatcher
{
public:
    Dispatcher()
    {
        std::cout << "In Dispatcher::Dispatcher\n";
    }
    virtual ~Dispatcher(){};

    void Dispatch(Client* client)
    {
        std::cout << "Dispatcher::Dispatch called by " << client << std::endl;
        client->ProcessEvent();
    }
};
class DispatcherTrampoline : public Dispatcher
{
public:
    using Dispatcher::Dispatcher;
};
class ClientTrampoline : public Client
{
public:
    using Client::Client;

    void ProcessEvent() override
    {
        PYBIND11_OVERLOAD(void,Client,ProcessEvent,);
    }
};
PYBIND11_MODULE(libTestCase,mod)
{
    py::class_<Client,ClientTrampoline> cli(mod,"Client");
    cli.def(py::init<Dispatcher* >());
    cli.def("ProcessEvent",&Client::ProcessEvent);
    cli.def_readwrite("PtrD",&Client::PtrD);

    py::class_<Dispatcher,DispatcherTrampoline> dsp(mod,"Dispatcher");
    dsp.def(py::init< >());
    dsp.def("Dispatch",&Dispatcher::Dispatch);
}

Python Test:

from build.libTestCase import Client,Dispatcher

class SomeClient(Client):
    def __init__(self,d):
        print("In SomeClient::__init__")
        super().__init__(d);

    def ProcessEvent(self):
        print("in SomeClient::ProcessEvent,about to call self.ProcessEvent")
        self.PtrD.Dispatch(self);

if __name__ == "__main__":
    dd = Dispatcher()
    cl = SomeClient(dd)
    dd.Dispatch(cl)

TERMINAL OUTPUT:

In Dispatcher::Dispatcher
In SomeClient::__init__
In Client::Client
Dispatcher::Dispatch called by 0x20bb270
in SomeClient::ProcessEvent,about to call self.ProcessEvent
Dispatcher::Dispatch called by 0x20bb270
THIS SHOULDN'T HAPPEN --In Client::ProcessEvent

Metadata

Metadata

Labels

holdersIssues and PRs regarding holders

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions