2013-09-21 53 views
2

我有问题使用Boost-Python包装Enum for Python。使用Boost-Python包装枚举

起初,我打算做类似的东西在的try-catch以下(我已经插入了我的整个代码如下)声明:

main_namespace["Motion"] = enum_<TestClass::Motion>("Motion") 
    .value("walk", TestClass::walk) 
    .value("bike", TestClass::bike) 
; 

一切都很好,并编制已完成。在运行时,我得到这个错误(这是没有意义的我):

AttributeError: 'NoneType' object has no attribute 'Motion' 

后来我决定写在我的代码使用BOOST_PYTHON_MODULE一个Python模块。 初始化Python解释器后,我想马上使用这个模块,但不知道如何(?)。以下是我的整个代码:

#include <boost/python.hpp> 
#include <iostream> 

using namespace std; 
using namespace boost::python; 

BOOST_PYTHON_MODULE(test) 
{ 
    enum_<TestClass::Motion>("Motion") 
     .value("walk", TestClass::walk) 
     .value("bike", TestClass::bike) 
    ; 
} 

int main() 
{ 
    Py_Initialize(); 

    try 
    {  
     object pyMainModule = import("__main__"); 
     object main_namespace = pyMainModule.attr("__dict__"); 

     //What previously I intended to do 
     //main_namespace["Motion"] = enum_<TestClass::Motion>("Motion") 
     // .value("walk", TestClass::walk) 
     // .value("bike", TestClass::bike) 
     //; 

     //I want to use my enum here 
     //I need something like line below which makes me able to use the enum! 

     exec("print 'hello world'", main_namespace, main_namespace); 
    } 
    catch(error_already_set const&) 
    { 
     PyErr_Print(); 
    } 

    Py_Finalize(); 
    return 0; 
} 

任何有用的知道包装和使用Python中的枚举将不胜感激! 在此先感谢

回答

3

AttributeError是在没有首先设置范围的情况下尝试创建Python扩展类型的结果。所述boost::python::enum_构造状态:

构建一个enum_物体保持从int衍生的Python扩展型被命名为name。当前作用域的d属性绑定到新的扩展类型。

嵌入Python时,要使用自定义Python模块,通常最容易使用PyImport_AppendInittab,然后按名称导入模块。

PyImport_AppendInittab("example", &initexample); 
... 
boost::python::object example = boost::python::import("example"); 

这里是表示两个枚举正在通过Boost.Python的暴露一个完整的例子。一个包含在由main导入的另一模块(example)中,另一个模块直接暴露在main中。

#include <iostream> 
#include <boost/python.hpp> 

/// @brief Mockup class with a nested enum. 
struct TestClass 
{ 
    /// @brief Mocked enum. 
    enum Motion 
    { 
    walk, 
    bike 
    }; 

    // @brief Mocked enum. 
    enum Color 
    { 
    red, 
    blue 
    }; 
}; 

/// @brief Python example module. 
BOOST_PYTHON_MODULE(example) 
{ 
    namespace python = boost::python; 
    python::enum_<TestClass::Motion>("Motion") 
    .value("walk", TestClass::walk) 
    .value("bike", TestClass::bike) 
    ; 
} 

int main() 
{ 
    PyImport_AppendInittab("example", &initexample); // Add example to built-in. 
    Py_Initialize(); // Start interpreter. 

    // Create the __main__ module. 
    namespace python = boost::python; 

    try 
    { 
    python::object main = python::import("__main__"); 
    python::object main_namespace = main.attr("__dict__"); 
    python::scope scope(main); // Force main scope 

    // Expose TestClass::Color as Color 
    python::enum_<TestClass::Color>("Color") 
     .value("red", TestClass::red) 
     .value("blue", TestClass::blue) 
     ; 

    // Print values of Color enumeration. 
    python::exec(
     "print Color.values", 
     main_namespace, main_namespace); 

    // Get a handle to the Color enumeration. 
    python::object color = main_namespace["Color"]; 
    python::object blue = color.attr("blue"); 

    if (TestClass::blue == python::extract<TestClass::Color>(blue)) 
     std::cout << "blue enum values matched." << std::endl; 

    // Import example module into main namespace. 
    main_namespace["example"] = python::import("example"); 

    // Print the values of the Motion enumeration. 
    python::exec(
     "print example.Motion.values", 
     main_namespace, main_namespace); 

    // Check if the Python enums match the C++ enum values. 
    if (TestClass::bike == python::extract<TestClass::Motion>(
      main_namespace["example"].attr("Motion").attr("bike"))) 
     std::cout << "bike enum values matched." << std::endl; 
    } 
    catch (const python::error_already_set&) 
    { 
    PyErr_Print(); 
    } 
} 

输出:

{0: __main__.Color.red, 1: __main__.Color.blue} 
blue enum values matched. 
{0: example.Motion.walk, 1: example.Motion.bike} 
bike enum values matched. 
+0

你的演示完美地契合了答案。感谢那。在你强制的范围内,这对我来说是一种骗术。这实际上解决了我的问题。我想问一个关于python范围的简单解释。其实我无法理解范围和命名空间之间的区别。 –

+1

@NOVIN:['scope'](http://www.boost.org/doc/libs/1_54_0/libs/python/doc/v2/scope.html#introduction)是一个Boost.Python结构,用于表示名称空间将包含新包装的类和函数。另外,如果你发现答案是有益的,你可以考虑[upvoting或accept](http://meta.stackoverflow.com/help/someone-answers)它。 –