创建带调用策略的属性 - boost::python

0 投票
1 回答
1935 浏览
提问于 2025-04-18 17:42

我有一些C++类,想要让它们在Python中使用。

class PlainOldData
{
     ...
};

class FancyClass
{
public:
    const PlainOldData& GetMyPOD() {return myPOD;}
private:
    PlainOldData myPOD;
};

因为我希望我的Python类看起来更像Python的风格,所以我想把myPOD作为一个属性来暴露出来。但是,当我尝试这样做的时候:

// expose with boost::python
BOOST_PYTHON_MODULE(mymod)
{
    class_<PlainOldData>("PlainOldData", init<>());

    // this fails
    class_<FancyClass>("FancyClass", init<>())
        .add_property("myPOD", &FancyClass::GetMyPOD);

}

我遇到了一个错误:error C2027: use of undefined type 'boost::python::detail::specify_a_return_value_policy_to_wrap_functions_returning<T>'

但是,如果我尝试指定一个调用策略,比如:

    class_<FancyClass>("FancyClass", init<>())
        .add_property("myPOD", &FancyClass::GetMyPOD, return_value_policy<copy_const_reference>());

我就会收到一个非常长的错误信息。

我想知道是否可以把这个函数作为属性暴露出来;我是不是做错了什么?

1 个回答

4

就像Python的 property() 可以接受Python的可调用对象一样,boost::python::class_::add_property() 这个函数也可以接受Python的可调用对象。这些对象可以通过CallPolicies 创建,比如通过boost::python::make_function() 返回的对象。

举个例子,原始代码中的属性可以这样暴露出来:

class_<FancyClass>("FancyClass", init<>())
  .add_property("myPOD", make_function(&FancyClass::GetMyPOD,
    return_value_policy<copy_const_reference>()));

下面是一个完整的简单示例:

#include <boost/python.hpp>

class egg {};

class spam
{
public:
  const egg& get_egg() { return egg_; }
private:
  egg egg_;
};

BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;
  python::class_<egg>("Egg");
  python::class_<spam>("Spam")
    .add_property("egg", python::make_function(&spam::get_egg,
      python::return_value_policy<python::copy_const_reference>()))
    ;
}

互动使用:

>>> import example
>>> spam = example.Spam()
>>> assert(spam.egg is not spam.egg) # unique identities as spam.egg
                                     # returns a copy
>>> egg1 = spam.egg
>>> assert(egg1 is not spam.egg)
>>> egg2 = spam.egg
>>> assert(egg1 is not egg2)

撰写回答