Boost.Python __init__() должен возвращать None, а не NoneType

У меня есть целая куча работающего кода C++, для которого я хочу написать привязки Python. Я пытаюсь использовать Boost.Python, так как это кажется самым простым способом заставить это работать, но это не помогает. Вот часть кода для модуля расширения, который я пытаюсь построить:

BOOST_PYTHON_MODULE(libpcap_ext) {
    using namespace boost::python;
    class_<PacketEngine>("PacketEngine")
        .def("getAvailableDevices", &PacketEngine_getAvailableDevices);
}

Bjam, кажется, испытывает боль и отказывается распознавать мой Pythonpath или разрешать мне связываться с libpcap, поэтому я использую CMake. Вот мой файл CMakeLists, который может нормально импортировать и создавать все (выводит libpcap.so, как и ожидалось):

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
IF(NOT CMAKE_BUILD_TYPE)
  SET(CMAKE_BUILD_TYPE "DEBUG")
  #SET(CMAKE_BUILD_TYPE "RELEASE")
  #SET(CMAKE_BUILD_TYPE "RELWITHDEBINFO")
  #SET(CMAKE_BUILD_TYPE "MINSIZEREL")
ENDIF()

FIND_PACKAGE(Boost 1.55.0)
find_package(PythonLibs REQUIRED)
IF(Boost_FOUND)
  INCLUDE_DIRECTORIES("${Boost_INCLUDE_DIRS}" "${PYTHON_INCLUDE_DIRS}")
  SET(Boost_USE_STATIC_LIBS OFF)
  SET(Boost_USE_MULTITHREADED ON)
  SET(Boost_USE_STATIC_RUNTIME OFF)
  FIND_PACKAGE(Boost 1.55.0 COMPONENTS python)

  ADD_LIBRARY(pcap_ext MODULE PacketWarrior/pcap_ext.cc PacketWarrior/PacketEngine.h PacketWarrior/PacketEngine.cc PacketWarrior/Packet.h PacketWarrior/Packet.cc)
  TARGET_LINK_LIBRARIES(pcap_ext pcap)
  TARGET_LINK_LIBRARIES(pcap_ext ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})
ELSEIF(NOT Boost_FOUND)
  MESSAGE(FATAL_ERROR "Unable to find correct Boost version. Did you set BOOST_ROOT?")
ENDIF()

ADD_DEFINITIONS("-Wall")

И мой файл pcap.py, который пытается использовать модуль:

import libpcap_ext
engine = libpcap_ext.PacketEngine()
print engine.getAvailableDevices()

Но всякий раз, когда я пытаюсь запустить модуль, я получаю следующую ошибку:

Traceback (most recent call last):
  File "../pcap.py", line 2, in <module>
    engine = libpcap_ext.PacketEngine()
TypeError: __init__() should return None, not 'NoneType

Я предполагаю, что это потому, что Boost.Python пытается использовать Python 3, и моя система по умолчанию - Python 2.7.3. Я попытался изменить свой файл user-config.jam (в моем каталоге boost_1_55_0), чтобы он указывал на Python 2.7, и попытался собрать:

# Configure specific Python version.
# using python : 2.7 : /usr/bin/python2.7 : /usr/include/python2.7 : /usr/lib ;

Инструкции по установке Boost.Python [0] кажутся мне неудачными, когда я пытаюсь собрать быстрый старт с bjam (много предупреждений), поэтому я попытался следовать инструкциям Boost Getting Started [1] для создания двоичного файла заголовка Python, что, я думаю, что вызывает эту проблему. Любые рекомендации относительно того, как это исправить, были бы удивительны, я потратил на это часы.

1 ответ

Решение

Эта ошибка, вероятно, из-за ссылки на неправильную библиотеку Python. Убедитесь, что ваше расширение и библиотека Boost Python связаны с установкой Python, которую вы используете для импорта модуля.

В Linux вы можете проверить, с какими библиотеками вы связаны ldd, На OS X otool -L делает то же самое. Так, например

otool -L libpcap_ext.so
otool -L /path/to/libboost_python-mt.dylib

должен перечислить библиотеку Python, с которой они связаны.

С CMake вы можете использовать переменную PYTHON_LIBRARY изменить, какая библиотека Python используется. Например, в командной строке вы можете установить его с помощью

cmake -DPYTHON_LIBRARY="/path/to/libpython2.7.dylib" source_dir

Наконец, в OS X быстрый и грязный способ (т.е. без перекомпиляции) изменить динамически связанные библиотеки install_name_tool -change,

Другие вопросы по тегам