1

我将一些 C++ 类暴露给嵌套了enum's 的 Python。查看boost.orgwiki.python.org上的示例文档,我看不到如何在输入范围后离开范围,以便返回到全局/模块范围。相反,每个后续范围都嵌套在前一个范围内。

举个例子:

#include <boost/python.hpp>

class Foo
{
public:
    enum Choose { eFoo, eBar };

    /* Default constructor with enum as required argument */
    Foo(Choose choice): m_choice(choice) {}
    ~Foo() {}

    Choose get() const { return m_choice; }

private:
    const Choose m_choice;

};


class Bar
{
};

BOOST_PYTHON_MODULE(foo)
{
    using namespace boost::python;
    scope global;

    /* Define Foo class, and a scope to go with it. */
    scope in_Foo = class_<Foo>
        ("Foo", init<Foo::Choose>())
        .def("rovalue", &Foo::get)
        ;

    /* Expose 'Choose' enum as Foo.Choose */
    enum_<Foo::Choose>("Choose")
        .value("Foo", Foo::eFoo)
        .value("Bar", Foo::eBar)
        ;

    /* How to get back to module scope??  */
    global;
    scope();

    /* This currently is exposed as Foo.Bar, but should just be Bar */
    class_<Bar>("Bar", init<>())
        ;
}

我已经尝试将该global;行更改为各种内容,但结果都相同:

$ g++ -fPIC -shared scope.cpp -o foo.so -lpython2.7 -I/usr/include/python2.7 -lboost_python
$ python -c 'import foo; print "Bar" in dir(foo)'
False
$ python -c 'import foo; print "Bar" in dir(foo.Foo)'
True

编辑:

再次查看 wiki.python.org,似乎在上面的示例中,正确的答案是使用scope within(global)恢复到模块级范围。实际上,这适用于上述示例。然而不幸的是,当我在实际应用程序中使用它时出现编译错误。

#include <boost/python.hpp>
using namespace boost;
BOOST_PYTHON_MODULE(foo)
{
    python::scope module_level;
    /* .... */
    python::scope python::within(module_level);
    /* ... */
}

编译错误:

error: invalid use of qualified-name 'boost::python::within'
4

1 回答 1

5

具有讽刺意味的是,这可能太聪明了,这可以使用 C++ 范围来完成。该boost::python::scope文档指出,当scope对象的生命周期结束时,当前范围会恢复到构造对象之前的scope状态。

BOOST_PYTHON_MODULE(foo)              // set scope to foo
{
  using namespace boost::python;
  {
    scope in_Foo = class_<Foo>        // define foo.Foo and set scope to foo.Foo
        ("Foo", init<Foo::Choose>())
        .def("rovalue", &Foo::get)
        ;

    enum_<Foo::Choose>("Choose")     // define foo.Foo.Choose
        .value("Foo", Foo::eFoo)
        .value("Bar", Foo::eBar)
        ;
  }                                  // revert scope, setting scope to foo

  class_<Bar>("Bar", init<>())       // define foo.Bar
      ;
}

虽然scope可以通过其他方式管理对象的生命周期,但我发现scope在 C++ 范围内使用对象作为自动变量为 C++ 命名空间提供了一些并行性。

于 2013-03-01T23:36:31.287 回答