5

我想使用 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 调用<>?

谢谢你,凯文

4

2 回答 2

7

公开Queuer类时,为每个成员函数定义一个__call__方法。Queuer::operator()Boost.Python 将根据类型处理适当的调度。唯一的复杂性是使用指向成员函数的语法引入的,因为调用者需要消除歧义&Queuer::operator()

此外,当尝试将 Python 中的派生类传递给带有 Base 类参数的 C++ 函数时,需要向 Boost.Python 公开一些附加信息:

  • 基 C++ 类需要使用class_. 例如,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.
于 2013-08-29T14:33:52.977 回答
0

谢谢你的帮助。

实际上我已经测试了静态转换解决方案。实际上,我需要在调用时传递qfc::lqs::Messageorqfc::lqs::Agent或。例如,对于继承自和分别。 qfc::lqs::Spamqueuer()qfc::lqs::Messageqfc::lqs::Agentqfc::Messageqfc::Agent

那么我可以在调用 operator() 以使签名对应于 operator() 时“强制转换”和“转换qfc::lqs::Messageqfc::lqs::Agentqfc::lqs::Spamqfc::Messageqfc::Agentqfc::Spam

这是为了避免如下所示的错误:

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'
于 2013-08-30T06:26:55.953 回答