Quando esporre la classe Queuer
, definire un metodo __call__
per ogni funzione Queuer::operator()
membro. Boost.Python gestirà l'invio appropriato in base ai tipi. L'unica complessità è introdotta con la sintassi della funzione pointer-to-member, in quanto il chiamante è necessario per disambiguare lo &Queuer::operator()
.
Inoltre, quando si tenta di passare classi derivate in Python a una funzione C++ con un parametro della classe Base, quindi deve essere esposto a Boost.Python alcune informazioni aggiuntive: esigenze classe
- La base C++ essere esposto con
class_
. Ad esempio, class_<BaseType>("Base")
.
- La classe derivata deve elencare esplicitamente le sue classi di base quando viene esposta con
bases_
. Ad esempio, class_<DerivedType, bases<BaseType> >("Derived")
. Con queste informazioni, Boost.Python può eseguire il cast corretto durante la spedizione.
Ecco un esempio completo:
#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()))
;
}
e il suo utilizzo:
>>> 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.
fonte
2013-08-29 14:33:52
consideri la modifica della domanda originale con questa informazione per i futuri utenti i quali corrono in questa domanda. Inoltre, ho aggiornato la risposta in base a ciò che ritengo allineare con altre domande.Se ho frainteso la domanda, sentitevi liberi di approfondirla. –