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 (
).
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
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)
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]pybind11::kwargs[/code]).
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]kwargs[/code] zur Startmethode von Foo.
Der Aufruf der Startmethode von Caller aus Python generiert jedoch immer den folgenden Fehler :
[code]TypeError: start() takes 1 positional argument but 2 were given
[/code]
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]#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;
};
[/code]
Hier sind die Bindungen:
[code]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);
}
[/code]
Hier ist der Py-Code
[code]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)
[/code]