【问题标题】:create boost-python nested namespace创建 boost-python 嵌套命名空间
【发布时间】:2011-10-14 09:24:04
【问题描述】:

使用 boost python 我需要创建嵌套命名空间。

假设我有以下 cpp 类结构:

namespace a
{
    class A{...}
    namespace b
    {
         class B{...}
    }
}

明显的解决方案不起作用:

BOOST_PYTHON_MODULE( a ) {
    boost::python::class_<a::A>("A")
     ...
    ;
    BOOST_PYTHON_MODULE(b){
        boost::python::class_<a::b::B>("B")
        ...
    ;
    }
}

导致编译时错误:linkage specification must be at global scope

有没有办法将可以从 Python 访问的 B 类声明为a.b.B?

【问题讨论】:

  • 我把它放在评论中是因为我从未尝试过:goo.gl/FxUHE
  • @Matthew - 谢谢,无论如何使用 PyImport_AddModule 是个好方法,这就是为什么 +1

标签: python boost boost-python


【解决方案1】:

你想要的是boost::python::scope。

Python 没有“命名空间”的概念,但您可以使用非常类似于命名空间的类:

#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/scope.hpp>
using namespace boost::python;

namespace a
{
    class A{};

    namespace b
    {
         class B{};
    }
}

class DummyA{};
class DummyB{};

BOOST_PYTHON_MODULE(mymodule)
{
    // Change the current scope 
    scope a
        = class_<DummyA>("a")
        ;

    // Define a class A in the current scope, a
    class_<a::A>("A")
        //.def("somemethod", &a::A::method)
        ;

    // Change the scope again, a.b:
    scope b
        = class_<DummyB>("b")
        ;

    class_<a::b::B>("B")
        //.def("somemethod", &a::b::B::method)
        ;
}

然后在 python 中,你有:

#!/usr/bin/env python
import mylib

print mylib.a,
print mylib.a.A
print mylib.a.b
print mylib.a.b.B

所有 a、a.A、a.b 和 a.b.B 实际上都是类,但您可以将 a 和 a.b 视为命名空间 - 而从不实际实例化它们

【讨论】:

  • 当我尝试这个时,我感到非常惊喜——我实际上并没有期望嵌套范围可以工作! Boost python 有时候真的很整洁。
  • 如果我想要mylib.a、mylib.a.A、mylib.b 和mylib.b.B 怎么办?如何“退出”“a”范围?
  • @robert boost::python::scope 对象使用 RAII,因此添加额外的 {} 以更改范围对象的生命周期;当作用域对象被销毁时,它会恢复创建时存在的命名空间。
  • @Autopulated:您的构造与文档中的构造不同。在文档中,范围对象是在分配时创建的,具有任意名称。那么用于创建子类包装器的名称就是封闭类的名称。您所做的是创建一个命名空间,然后创建一个具有相同名称的范围对象,然后在为子类定义包装器时使用该命名空间/范围对象名称,即class_&lt;a::A&gt;。你能解释一下这样做的理由吗?
  • @FaheemMitha:因为我不知道构造函数的存在! (而且我在the documentation? 中没有看到)使用类反映了它在 python 中的工作方式,所以这是我尝试过的唯一方法。
【解决方案2】:

虚拟类的技巧很好,但不允许:

import mylib.a
from mylib.a.b import B

因此,改为使用 PyImport_AddModule()。您可以在以下文章中找到完整的示例:Packages in Python extension modules,作者是 Vadim Macagon。

简而言之:

namespace py = boost::python;
std::string nested_name = py::extract<std::string>(py::scope().attr("__name__") + ".nested");
py::object nested_module(py::handle<>(py::borrowed(PyImport_AddModule(nested_name.c_str()))));
py::scope().attr("nested") = nested_module;
py::scope parent = nested_module;
py::class_<a::A>("A")...

【讨论】:

  • 詹姆斯的上述回答不允许import mylib.a这一点非常重要。读者请注意!
猜你喜欢
  • 1970-01-01
  • 2012-10-30
  • 1970-01-01
  • 2011-01-06
  • 1970-01-01
  • 2019-08-30
  • 2015-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多