Wenn die Queuer
Klasse auszusetzen, definieren eine __call__
Methode für jede Funktion Queuer::operator()
Mitglied. Boost.Python wird das entsprechende Dispatching basierend auf den Typen durchführen. Die einzige Komplexität wird mit der Pointer-zu-Member-Funktionssyntax eingeführt, da der Aufrufer &Queuer::operator()
disambiguieren muss.
Zusätzlich, wenn versucht wird, um abgeleitete Klassen in Python zu einer C++ Funktion mit einem Parameter der Basisklasse übergibt, dann einige zusätzliche Informationen Boost.Python ausgesetzt werden muss:
- Die Base C++ Klasse Bedürfnisse mit
class_
ausgesetzt werden. Zum Beispiel class_<BaseType>("Base")
.
- Die abgeleitete Klasse muss ihre Basisklassen explizit auflisten, wenn sie mit
bases_
angezeigt wird. Zum Beispiel class_<DerivedType, bases<BaseType> >("Derived")
. Mit diesen Informationen kann Boost.Python während des Versands richtiges Casting durchführen.
Hier ist ein komplettes Beispiel:
#include <iostream>
#include <boost/python.hpp>
// Mockup classes.
struct AgentBase {};
struct MessageBase {};
struct QueueBase {};
struct SpamBase {};
struct Agent: AgentBase {};
struct Message: MessageBase {};
struct Queue: QueueBase {};
struct Spam: SpamBase {};
// Class with overloaded operator().
class Queuer
{
public:
void operator()(const AgentBase&, const MessageBase&) const
{
std::cout << "Queuer::operator() with Agent." << std::endl;
}
void operator()(const QueueBase&, const MessageBase&) const
{
std::cout << "Queuer::operator() with Queue." << std::endl;
}
void operator()(const SpamBase&, const MessageBase&) const
{
std::cout << "Queuer::operator() with Spam." << std::endl;
}
};
/// Depending on the overlaod signatures, helper types may make the
/// code slightly more readable by reducing pointer-to-member-function syntax.
template <typename A1>
struct queuer_overload
{
typedef void (Queuer::*type)(const A1&, const MessageBase&) const;
static type get(type fn) { return fn; }
};
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
// Expose only the base class types. Do not allow the classes to be
// directly initialized in Python.
python::class_<AgentBase >("AgentBase", python::no_init);
python::class_<MessageBase>("MessageBase", python::no_init);
python::class_<QueueBase >("QueueBase", python::no_init);
python::class_<SpamBase >("SpamBase", python::no_init);
// Expose the user types. These classes inerit from their respective
// base classes.
python::class_<Agent, python::bases<AgentBase> >("Agent");
python::class_<Message, python::bases<MessageBase> >("Message");
python::class_<Queue, python::bases<QueueBase> >("Queue");
python::class_<Spam, python::bases<SpamBase> >("Spam");
// Disambiguate via a varaible.
queuer_overload<AgentBase>::type queuer_op_agent = &Queuer::operator();
python::class_<Queuer>("Queuer")
// Disambiguate via a variable.
.def("__call__", queuer_op_agent)
// Disambiguate via a helper type.
.def("__call__", queuer_overload<QueueBase>::get(&Queuer::operator()))
// Disambiguate via explicit cast.
.def("__call__",
static_cast<void (Queuer::*)(const SpamBase&,
const MessageBase&) const>(
&Queuer::operator()))
;
}
Und seine Nutzung:
>>> import example
>>> queuer = example.Queuer()
>>> queuer(example.Agent(), example.Message())
Queuer::operator() with Agent.
>>> queuer(example.Queue(), example.Message())
Queuer::operator() with Queue.
>>> queuer(example.Spam(), example.Message())
Queuer::operator() with Spam.
Betrachten Sie die ursprüngliche Frage mit dieser Information Bearbeitung für zukünftige Benutzer, die in dieser Frage führen. Außerdem aktualisierte ich die Antwort basierend auf dem, was meiner Meinung nach mit mehr der Frage übereinstimmt.Wenn ich die Frage missverstanden habe, kann ich mich gerne darauf konzentrieren. –