2013-09-21 80 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)它。 –