2013-03-22 4 views
4

Извините за такое общее название, но я не совсем уверен, что именно я пропал без вести или что я делаю неправильно. Моя цель - построить расширение python, используя boost.python под cygwin и избегая инструментов boost.build, которые используют make вместо bjam. Последний способ работал для меня неплохо, но теперь я хочу сделать это таким образом. Я решил много вопросов по поиску и поиску похожих тем, что помогло мне разобраться в некоторых трюках и двигаться вперед. Но на последнем этапе, похоже, есть некоторые проблемы. Я попытаюсь описать все свои шаги в некоторых деталях в надежде, что этот пост может быть полезен другим в будущем, а также лучше описать настройку.вручную создает расширение python в cygwin с boost.python

Потому что я не совсем уверен, что оригинальные (из различных Cygwin хранилищ) установок как питона и повысить я решил установить их с нуля в моем домашнем каталоге, так вот что я делаю:

  1. сначала установите python. Я пропущу детали для этого, это более или менее просто. Для последнего описания это просто путь:

    /home/Alexey_2/Soft/python2.6 - это PYTHONPATH, также входящий в состав ПУТЬ

  2. работает над повышением:

    а) распаковка источник подталкивание в

    /home/Alexey_2/Soft/boost_1_50_0 - this is BOOST_ROOT 
    

    б), что делает bjam. сначала перейдите в каталог:

    /home/Alexey_2/Soft/boost_1_50_0/tools/build/v2 
    

    рядом, вызовите bootstrap.sh это в конечном счете, создает b2 и bjam исполняемые файлы в этом каталоге. В .bash_profile добавьте этот каталог в PATH, чтобы мы могли вызвать bjam. Вот и после каждого будущего редактирует из .bash_profile перезапустить Cygwin, чтобы сделать изменения приходят к эффекту

    с) еще в

    /home/Alexey_2/Soft/boost_1_50_0/tools/build/v2 
    

    каталога - редактирования пользовательского config.jam, чтобы bjam знать который использовать python. Так что в моем случае я только добавить одну строку:

    using python : 2.6 : /home/Alexey_2/Soft/python2.6/bin/python2.6 : /home/Alexey_2/Soft/python2.6/include/python2.6 : /home/Alexey_2/Soft/python2.6/bin ; 
    

    в Lib-пути (последняя запись) я поставил /home/Alexey_2/Soft/python2.6/bin, потому что он содержит libpython2.6.dll

    d) хорошо. теперь мы можем создавать библиотеки boost-python. перейти к BOOST_ROOT каталог и выполнить команду

    bjam --with-python toolset=gcc link=shared 
    

    это создает необходимые библиотеки (cygboost_python.dll и libboost_python.dll.a) и помещает их в

    /home/Alexey_2/Soft/boost_1_50_0/stage/lib 
    
  3. расширение здания питона.

    вот моя простая тестовая программа (на самом деле часть кода примера)

    // file xyz.cpp 
    #include <boost/python.hpp> 
    #include <iostream> 
    #include <iomanip> 
    using namespace std; 
    using namespace boost::python; 
    
    class Hello 
    { 
        std::string _msg; 
    public: 
        Hello(std::string msg){_msg = msg;} 
        void set(std::string msg) { this->_msg = msg; } 
        std::string greet() { return _msg; } 
    }; 
    
    BOOST_PYTHON_MODULE(xyz) 
    { 
        class_<Hello>("Hello", init<std::string>()) 
        .def("greet", &Hello::greet) 
        .def("set", &Hello::set) 
        ; 
    } 
    

    А вот Makefile:

    FLAGS= -fno-for-scope -O2 -fPIC 
    CPP=c++ 
    
    # BOOST v 1.50.0 
    p1=/home/Alexey_2/Soft/boost_1_50_0 
    pl1=/home/Alexey_2/Soft/boost_1_50_0/stage/lib 
    
    # PYTHON v 2.6 
    p2=/home/Alexey_2/Soft/python2.6/include/python2.6 
    pl2=/home/Alexey_2/Soft/python2.6/bin 
    
    
    I=-I${p1} -I${p2} 
    L=-L${pl1} -lboost_python -L${pl2} -lpython2.6 
    
    all: xyz.so 
    
    xyz.o: xyz.cpp 
        ${CPP} ${FLAGS} ${I} -c xyz.cpp 
    
    xyz.so: xyz.o 
        ${CPP} ${FLAGS} -shared -o xyz.so xyz.o ${L} 
    
    clean: 
        rm *.o 
        rm xyz.so 
    

Некоторые комментарии:

  1. Библиотечные пути установлены, и я компилирую против prope r библиотек (см. больше: compile some code with boost.python by mingw in win7-64bit).

  2. Приведенная выше ссылка объясняет, почему важно настроить user-config.jam - я сделал это на шаге 1c.

  3. Для того, чтобы избежать возможных проблем (как указано в приведенной выше ссылке, а также в Cannot link boost.python with mingw (хотя для MinGW)) с библиотеками boost.python любил статически я использовать

    link=shared 
    

    в качестве аргумента bjam (см 1d)

  4. Как объяснено здесь: MinGW + Boost: undefined reference to `[email protected]' библиотеки, с которыми один хочет, чтобы собрать что-то должны быть перечислены после объектных файлов, поэтому мы имеем:

    ${CPP} ${FLAGS} -shared -o xyz.so xyz.o ${L} 
    

    и не

    ${CPP} ${FLAGS} -shared ${L} -o xyz.so xyz.o 
    

А вот кусок моего .bash_profile (в конце концов), где я определить переменные окружения:

# Python 
export PATH=/home/Alexey_2/Soft/python2.6/bin:$PATH 
export PYTHONPATH=/home/Alexey_2/Soft/python2.6 
export LD_LIBRARY_PATH=/home/Alexey_2/Soft/python2.6/lib:/home/Alexey_2/Soft/python2.6/bin:$LD_LIBRARY_PATH 

# Boost 
export BOOST_ROOT=/home/Alexey_2/Soft/boost_1_50_0 
export LD_LIBRARY_PATH=/home/Alexey_2/Soft/boost_1_50_0/stage/lib:$LD_LIBRARY_PATH 
export PATH=/home/Alexey_2/Soft/boost_1_50_0/stage/lib:$PATH 

# bjam 
export PATH=/home/Alexey_2/Soft/boost_1_50_0/tools/build/v2:$PATH 

Наконец, к этой проблеме. С учетом указанных выше установки я смог успешно создать файл питон объекта расширения:

xyz.so 

Однако, когда я проверить его простой скрипт:

# this is a test.py script 
import xyz 

ImportError приходит:

$ python test.py 
Traceback (most recent call last): 
    File "test.py", line 1, in <module> 
    import xyz 
ImportError: No module named xyz 

Было отмечено, что причиной такой проблемы может быть неправильный исполняемый файл python, но это не тот случай:

$ which python 
/home/Alexey_2/Soft/python2.6/bin/python 

, что ожидается (примечание питон является символической ссылкой на python2.6 из этого каталога)

Вот еще одна полезная информация у меня есть:

$ ldd xyz.so 
    ntdll.dll => /cygdrive/c/Windows/SysWOW64/ntdll.dll (0x76fa0000) 
    kernel32.dll => /cygdrive/c/Windows/syswow64/kernel32.dll (0x76430000) 
    KERNELBASE.dll => /cygdrive/c/Windows/syswow64/KERNELBASE.dll (0x748e0000) 
    cygboost_python.dll => /home/Alexey_2/Soft/boost_1_50_0/stage/lib/cygboost_python.dll (0x70cc0000) 
    cygwin1.dll => /usr/bin/cygwin1.dll (0x61000000) 
    cyggcc_s-1.dll => /usr/bin/cyggcc_s-1.dll (0x6ff90000) 
    cygstdc++-6.dll => /usr/bin/cygstdc++-6.dll (0x6fa90000) 
    libpython2.6.dll => /home/Alexey_2/Soft/python2.6/bin/libpython2.6.dll (0x67ec0000) 
    ??? => ??? (0x410000) 

мне интересно, что

??? => ??? (0x410000) 

может означать. Может быть, это то, что мне не хватает. Но что это? Любые комментарии и предложения (а не только о последнем вопросе) очень ценятся.

EDIT:

По предложению (twsansbury), рассматривающего питон пути поиска модулей с -vv вариантом:

python -vv test.py 

дает

# trying /home/Alexey_2/Programming/test/xyz.dll 
# trying /home/Alexey_2/Programming/test/xyzmodule.dll 
# trying /home/Alexey_2/Programming/test/xyz.py 
# trying /home/Alexey_2/Programming/test/xyz.pyc 
... 
# trying /home/Alexey_2/Soft/python2.6/lib/python2.6/site-packages/xyz.dll 
# trying /home/Alexey_2/Soft/python2.6/lib/python2.6/site-packages/xyzmodule.dll 
# trying /home/Alexey_2/Soft/python2.6/lib/python2.6/site-packages/xyz.py 
# trying /home/Alexey_2/Soft/python2.6/lib/python2.6/site-packages/xyz.pyc 
Traceback (most recent call last): 
    File "test.py", line 1, in <module> 
    import xyz 
ImportError: No module named xyz 

Первый каталог, откуда я вызовите python для запуска скрипта. Основной вывод заключается в том, что cygwin python ищет модули (библиотеки) со стандартным расширением Windows - dll (среди других 3 типов), а не .so, как я изначально ожидал от стиля эмуляции Linux cygwin. Таким образом, изменяя следующие строки в предыдущем Makefile для:

all: xyz.dll 

xyz.o: xyz.cpp 
     ${CPP} ${FLAGS} ${I} -c xyz.cpp 

xyz.dll: xyz.o 
    ${CPP} ${FLAGS} -shared -o xyz.dll xyz.o ${L} 

clean: 
    rm *.o 
    rm xyz.dll 

производит xyz.dll, которые успешно могут быть загружены:

python -vv test.py 

теперь дает:

Python 2.6.8 (unknown, Mar 21 2013, 17:13:04) 
[GCC 4.5.3] on cygwin 
Type "help", "copyright", "credits" or "license" for more information. 
# trying /home/Alexey_2/Programming/test/xyz.dll 
dlopen("/home/Alexey_2/Programming/test/xyz.dll", 2); 
import xyz # dynamically loaded from /home/Alexey_2/Programming/test/xyz.dll 
+0

+1 Хорошо объясненный вопрос и исследование усилий. –

ответ

1

Это ImportError, как правило, не Boost.Python. Скорее, это обычно указывает, что xyz не находится в Python Module Search Path.

Чтобы отладить это, рассмотрите возможность запуска python с аргументами -vv. Это заставит python печатать сообщение для каждого файла, который проверяется при попытке импорта xyz. Независимо от того, процесс сборки выглядит правильно, поэтому проблема, скорее всего, является результатом расширения файла или модуля, который не находится в пути поиска.

Я не уверен, как Cygwin будет взаимодействовать с поведением загрузки Python. Однако:

  • На Windows, расширения python имеют расширение .pyd.
  • В Linux расширения python имеют расширение .so.

Кроме того, убедитесь, что xyz библиотека находится в одном из следующих способов:

  • в каталог, содержащий test.py скрипт (или текущий каталог).
  • Каталог, указанный в переменной окружения PYTHONPATH.
  • Зависимый от установки каталог по умолчанию.

Если нерешенной библиотека показано на ldd приводит к ошибкам, оно обычно проявляется как ImportError с сообщением, указывающим неопределенные ссылки.

+0

спасибо, twsansbury! теперь все работает нормально - я добавил соответствующий обходной путь к моему оригинальному сообщению. – user938720