2014-08-27 88 views
0

從嵌入式Python中提取數據我想學習一點boost :: python,並且我被困在從python字符串中提取數據。使用Boost :: Python

目前,我能夠乾淨地編譯,但是在執行代碼時,我收到了一個段錯誤。我已經將seg-fault縮小到了實際使用boost :: python :: extract的那一行。

我希望得到指導。提前致謝!

爲了方便起見,我提供了一個GitHub庫:https://github.com/brianbruggeman/boost_python_hello_world/tree/feature/stack_overflow

.cpp的代碼(say_hello.cpp):

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

namespace bp = boost::python; 

// Embedding python 
int main(int argc, char** argv) { 
    int data = 0; 
    Py_Initialize(); 
    PyRun_SimpleString("data = 1"); 
    bp::object module(bp::handle<>(bp::borrowed(PyImport_AddModule("__main__")))); 
    bp::object dictionary = module.attr("__dict__"); 
    bp::object data_obj = dictionary["data"]; 
    // Error: The following line has the segmentation fault... 
    data = bp::extract<int>(data_obj); 
    std::cout << "data = " << data << std::endl; 
    Py_Finalize(); 
    return 0; 
} 

我在做什麼錯?爲了完整起見,我使用的是Mac OS X的小牛隊和我包括下面的CMakeLists.txt文件:

project(hello) 
cmake_minimum_required(VERSION 2.8) 

FIND_PACKAGE(PythonInterp) 
FIND_PACKAGE(PythonLibs) 
FIND_PACKAGE(Boost COMPONENTS python) 

include_directories(${PYTHON_INCLUDE_DIRS} ${Boost_INCLUD_DIRS}) 
link_directories(${PYTHON_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS}) 

add_executable(hello say_hello.cpp) 
target_link_libraries(hello 
    ${Boost_LIBRARIES} 
    ${PYTHON_LIBRARIES}) 

Python的編譯,並使用自制軟件安裝:

brew install python 

加速編譯和安裝使用自制軟件:

brew install boost --with-python 

Edit(對於升壓蟒蛇新安裝):

brew install --build-from-source boost-python 

回答

0

代碼很好。構建過程就是問題。

BREW是buildling針對來自釀造的蟒包安裝的Python庫的libboost_python庫:

$ otool -L $(brew list boost | grep "libboost_python.dylib") 
/usr/local/Cellar/boost/1.55.0_2/lib/libboost_python.dylib: 
    /usr/local/lib/libboost_python.dylib (...) 
    /usr/local/Frameworks/Python.framework/Versions/2.7/Python (...) <-- brew 
    ... 

然而,CMake的是連接靠設置Python庫的OSX系統:

$ (mkdir build && cd build && cmake ../) 
... 
-- Found PythonLibs: /usr/lib/libpython2.7.dylib (found version "2.7.5") 
... 

因此,程序和Boost.Python鏈接到不同的Python庫,導致未定義的行爲。要解決此問題,請修復FindPythonLibs.cmake文件或更新CMakeLists.txt以顯式鏈接到brew提供的Python庫。


下面是一個完整CMakeLists.txt例子是,PYTHON_LIBRARIES變量明確設置由沖泡我的系統上安裝Python庫:

project(hello) 
cmake_minimum_required(VERSION 2.8) 

find_package(PythonLibs) 
set(PYTHON_LIBRARIES /usr/local/Frameworks/Python.framework/Versions/2.7/Python) 
find_package(Boost COMPONENTS python) 

include_directories(${PYTHON_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) 
link_directories(${Boost_LIBRARY_DIRS}) 

add_executable(hello say_hello.cpp) 
target_link_libraries(hello 
    ${Boost_LIBRARIES} 
    ${PYTHON_LIBRARIES}) 

及其用法:

$ (mkdir build && cd build && cmake ../ && make) 
... 
-- Found PythonLibs: /usr/lib/libpython2.7.dylib (found version "2.7.5") 
... 
Scanning dependencies of target hello 
[100%] Building CXX object CMakeFiles/hello.dir/say_hello.cpp.o 
Linking CXX executable hello 
[100%] Built target hello 
$ ./build/hello 
data = 1 

注意PythonLibs仍將打印找到的庫,但PYTHON_LIBRARIES變量已明確設置爲相應的庫。


其他一些注意事項:

  • Boost.Python的不支持安全調用Py_Finalize()。根據Embedding - Getting started部分:

    請注意,此時您不能撥打Py_Finalize()來停止解釋器。這可能會在未來版本的boost.python中修復。

  • 嵌入時,我經常發現它有助於使用try/catch塊,捕捉boost::python::error_already_set異常和打印錯誤:

    Py_Initialize(); 
    try 
    { 
        // ... 
    } 
    catch (boost::python::error_already_set&) 
    { 
        PyErr_Print(); 
    } 
    
+0

謝謝你的見解! (y) – 2014-08-31 18:55:31

+0

今天,應該安裝boost-python: brew install --build-from-source boost-python – 2014-12-16 18:18:59