Метод виртуального дочернего класса Pybind11 не вызывается во время рекурсии, вместо него вызывается Base

У меня есть простой тестовый пример полиморфизма, который работает не совсем правильно. У меня есть два класса C++, Client и Dispatcher. Диспетчер имеет метод "Dispatch", который принимает Client* в качестве входных данных и вызывает клиентский виртуальный метод ProcessEvent(). Я сделал оба этих класса доступными для Python, используя код ниже. Я получил класс Client как класс Python SomeClient и переопределил его функцию ProcessEvent. Когда я вызываю "Dispatch" из любой точки, кроме EXCEPT внутри метода SomeClient:: ProcessEvent, все работает как положено, я получаю отчет от дочернего класса. Но когда я вызываю Dispatch из SomeClient:: ProcessEvent, вызывается базовый класс ProcessEvent. Есть идеи, что здесь может пойти не так? Я ожидаю получить бесконечную рекурсию, в результате которой SomeClient:: ProcessEvent будет вызываться вечно.

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:

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)

ТЕРМИНАЛЬНЫЙ ВЫХОД:

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

0 ответов

Другие вопросы по тегам