我想使用Boost :: Python绑定operator(),但我真的不知道如何做到这一点。考虑一下这个例子:
C ++:
class Queuer
{
public:
void Queuer::operator()(const qfc::Queue & iq, const qfc::Message & im) const;
void Queuer::operator()(const qfc::Agent & ia, const qfc::Message & im) const;
// some other overloaded operator() methods
};
所以在Python脚本中,导入我正在使用的模块(称为qfc)之后,我想这样做:
的Python:
>>> queuer = qfc.Queuer()
// instantiating a Message an Agent and a Queue object
>>> queuer(queue,message)
>>> queuer(agent,message)
>>> ...
你对如何做到这一点有什么想法吗?也许用boost :: python调用<>?
谢谢你, 凯文
答案 0 :(得分:7)
在公开Queuer
类时,为每个Queuer::operator()
成员函数定义__call__
方法。 Boost.Python将根据类型处理适当的调度。使用指向成员函数的语法引入了唯一的复杂性,因为调用者需要消除&Queuer::operator()
的歧义。
此外,当尝试将Python中的派生类传递给带有Base类参数的C ++函数时,需要将一些其他信息公开给Boost.Python:
class_
公开基础C ++类。例如,class_<BaseType>("Base")
。bases_
公开时需要显式列出其基类。例如,class_<DerivedType, bases<BaseType> >("Derived")
。有了这些信息,Boost.Python可以在调度时进行适当的投射。这是一个完整的例子:
#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()))
;
}
及其用法:
>>> 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.
答案 1 :(得分:0)
感谢您的帮助。
实际上我已经测试了静态演员解决方案。实际上,我需要在调用qfc::lqs::Message
时传递qfc::lqs::Agent
或qfc::lqs::Spam
或queuer()
。例如qfc::lqs::Message
,qfc::lqs::Agent
分别从qfc::Message
和qfc::Agent
继承。
我可以在调用operator()时“qfc::lqs::Message
,qfc::lqs::Agent
和qfc::lqs::Spam
”qfc::Message
,qfc::Agent
和qfc::Spam
这样签名对应于operator()?
这样可以避免以下错误:
error: invalid static_cast from type '<unresolved overloaded function type>' to type 'void (qfc::lqs::Queuer::*)(const qfc::lqs::Queue&, const qfc::lqs::Message&)const'