Unterklassen von C++-Klassen in Python mit Pybind11 – kann ich eine virtuelle Methode haben, die Kwargs übernimmt?

Post a reply

Smilies
:) :( :oops: :chelo: :roll: :wink: :muza: :sorry: :angel: :read: *x) :clever:
View more smilies

BBCode is ON
[img] is ON
[flash] is OFF
[url] is ON
Smilies are ON

Topic review
   

Expand view Topic review: Unterklassen von C++-Klassen in Python mit Pybind11 – kann ich eine virtuelle Methode haben, die Kwargs übernimmt?

by Anonymous » 27 Dec 2024, 12:49

in meinem C++/Pybind11-Projekt habe ich eine C++-Klasse Foo, die in Python in Unterklassen unterteilt werden kann. Wie üblich durchlief ich den üblichen Prozess, eine Trampolinklasse PyFoo und die üblichen Bindungen zu haben.
Jetzt stellte sich jedoch heraus, dass es nützlich sein würde, den Anfang zu haben Methode von Foo, um Schlüsselwortargumente zu übernehmen (

Code: Select all

pybind11::kwargs
).
In meinem Projekt habe ich auch eine Klasse Caller, die eine Sammlung von Foos enthält. Der Aufrufer stellt eine Methode start bereit, die die start-Methode des erforderlichen foo aufruft und die
weiterleitet

Code: Select all

kwargs
zur Startmethode von Foo.
Der Aufruf der Startmethode von Caller aus Python generiert jedoch immer den folgenden Fehler :

Code: Select all

TypeError: start() takes 1 positional argument but 2 were given
Hier ist der vollständige Code zur Reproduktion des Problems. Ist das möglich und wenn ja, was muss ich tun, damit es funktioniert?
Datei foo.h/cpp

Code: Select all

#pragma once

#include
#include 

// c++ class
class Foo {
public:
Foo() = default;

virtual ~Foo() = default;

virtual void start(pybind11::kwargs args) {}

virtual void update(double) {}

};

// trampoline class
class PyFoo : public Foo {
public:
using Foo::Foo;  // Inherit constructors

void PyFoo::start(pybind11::kwargs args) override {
std::cout start(std::move(args));
}
void add(pybind11::object foo) {
_objs.push_back(foo);
_controllers.push_back(foo.cast());
}
private:
std::vector _objs;
std::vector _controllers;

};
Hier sind die Bindungen:

Code: Select all

namespace py = pybind11;

PYBIND11_MODULE(untitled3, m) {

py::class_(m, "Foo")
.def(py::init());

py::class_(m, "Caller")
.def(py::init())
.def("add", &Caller::add)
.def("start", &Caller::start);
}

Hier ist der Py-Code

Code: Select all

import untitled3

class Bar(untitled3.Foo):

def __init__(self):
super().__init__()

def start(self, **kwargs):
print('ici')

def update(self, dt):
print('here')

c = untitled3.Caller()
c.add(Bar())
c.add(Bar())
c.start(1)

Top