создать вложенное пространство имен boost-python - PullRequest
6 голосов
/ 14 октября 2011

С помощью 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

Есть ли способ объявить класс B, к которому будет обращаться из Python, как a.b.B?

Ответы [ 2 ]

12 голосов
/ 18 ноября 2011

То, что вы хотите, это 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 так же, как пространства имен - и никогда не создавать их на самом деле

10 голосов
/ 19 июня 2013

Трюк с фиктивными классами вполне подходит, но не позволяет:

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

Так что вместо этого используйте PyImport_AddModule ().Вы можете найти полнофункциональные примеры в следующей статье: Пакеты в модулях расширения Python , от Вадима Макагона.

Короче:

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")...
...