【问题标题】:Hello world with boost python and python 3.2你好世界与boost python和python 3.2
【发布时间】:2011-11-03 23:43:19
【问题描述】:

所以我正在尝试使用 boost python 连接 python 3.2 和 c++,并且遇到了很多问题。我终于让它使用 2.7 库进行编译并且它可以工作,但我似乎无法让它与 python 3.2 一起工作。

这是 C++ 代码

#include <iostream>

using namespace std;

void say_hello(const char* name) {
    cout << "Hello " <<  name << "!\n";
}

int main(){return 0;}

#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
using namespace boost::python;

BOOST_PYTHON_MODULE(hello)
{
    def("say_hello", say_hello);
}

如果我使用 2.7 库编译它,它工作得很好,但是当我使用 3.2 库时,我会从 libboost_python.so 获得大量未定义的引用

否则我写了一点python让它工作:

from distutils.core import setup
from distutils.extension import Extension

setup(name="PackageName",
    ext_modules=[
        Extension("hello", ["testBoost.cpp"],
        libraries = ["boost_python"])
    ])

这将使用python 3.2或2.7构建创建一个so,但是当我打开python 3解释器并尝试导入so时,它再次给我来自libboost_python.so的错误未定义符号PyClass_Type。有任何想法吗? boost python与python 3.x兼容吗?

如果信息有用,这里是我尝试使用 3.2 编译:

   $ g++ testBoost.cpp -I/usr/include/python3.2 -I/usr/local/include/boost/python -lboost_python -lpython3.2mu 
    /tmp/ccdmU1Yu.o: In function `PyInit_hello':
    testBoost.cpp:(.text+0xc2): undefined reference to `boost::python::detail::init_module(PyModuleDef&, void (*)())'
    /usr/local/lib/libboost_python.so: undefined reference to `PyString_Size'
    /usr/local/lib/libboost_python.so: undefined reference to `PyFile_FromString'
    /usr/local/lib/libboost_python.so: undefined reference to `PyString_Type'
    /usr/local/lib/libboost_python.so: undefined reference to `PyInt_Type'
    /usr/local/lib/libboost_python.so: undefined reference to `PyString_FromString'
    /usr/local/lib/libboost_python.so: undefined reference to `PyString_FromStringAndSize'
    /usr/local/lib/libboost_python.so: undefined reference to `Py_InitModule4_64'
    /usr/local/lib/libboost_python.so: undefined reference to `PyString_FromFormat'
    /usr/local/lib/libboost_python.so: undefined reference to `PyNumber_Divide'
    /usr/local/lib/libboost_python.so: undefined reference to `PyNumber_InPlaceDivide'
    /usr/local/lib/libboost_python.so: undefined reference to `PyInt_AsLong'
    /usr/local/lib/libboost_python.so: undefined reference to `PyString_InternFromString'
    /usr/local/lib/libboost_python.so: undefined reference to `PyClass_Type'
    /usr/local/lib/libboost_python.so: undefined reference to `PyString_AsString'
    /usr/local/lib/libboost_python.so: undefined reference to `PyInt_FromLong'
    /usr/local/lib/libboost_python.so: undefined reference to `PyFile_AsFile'
    collect2: ld returned 1 exit status

python 3解释器的错误是

File "<stdin>", line 1, in <module>
ImportError: /usr/local/lib/libboost_python.so.1.47.0: undefined symbol: PyClass_Type

感谢您的帮助!

【问题讨论】:

  • 如果可以的话,您可能需要考虑研究 SWIG 而不是 Boost.Python。它需要的样板代码要少得多,而且我以前很容易让它与 Python3 一起工作。
  • @Sean 我不确定你在说什么样板代码;我的 boost/python 只需 5 行额外代码即可流畅运行。

标签: c++ python boost g++ boost-python


【解决方案1】:

我在 Ubuntu 12.04 上遇到了完全相同的问题。我安装了 1.48 版本的库,并且必须使用 libboost_python-py32.so 而不是 libboost_python.so 链接,此后链接器错误消失了。

【讨论】:

    【解决方案2】:

    上面的c++代码编译成一个带有

    的模块
    $ g++ testBoost.cpp -I/usr/include/python3.2 -I/usr/local/include/boost/python -lboost_python3 -lpython3.2mu -o hello.so -shared
    

    这个编译命令添加了-lboost_python3-shared,以及python扩展模块的命名约定。如果您还没有安装 python3-dev 包,并使用 python3 配置/构建/安装 boost,您还应该安装。

    在 python 3 中,我可以执行以下操作:

    $ python3
    Python 3.2 (r32:88445, Mar 25 2011, 19:28:28) 
    [GCC 4.5.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import hello
    >>> hello.say_hello('bill')
    Hello bill!
    >>>
    

    那时你应该去参加比赛了。

    【讨论】:

    • 我尝试使用 -lboost_python3 但仍然遇到同样的错误,并且我已经将我的 jam 文件更改为指向 python 3
    • 好的,所以我按照您的说明进行了编译,它告诉我需要使用 -fpic 重新编译,这很有效,最后我得到了 .so。但是,现在,当我尝试在 python 中导入时,我收到一条错误消息: ImportError: /usr/local/lib/libboost_python3.so.1.47.0: undefined symbol: PyClass_Type
    【解决方案3】:

    虽然这个讨论很老,但仅供记录: 修改 project-config.jam 以将 python 版本更改为您的设置

    # Python configuration
    using python : 3.4 : /usr ;
    

    然后构建提升:

    ./b2 clean
    ./b2 --with-python link=static cxxflags="-std=c++11 -fPIC" variant=release stage
    ./b2 --with-python link=static cxxflags="-std=c++11 -fPIC" variant=release install
    

    后面的命令需要超级用户权限。然后移动到包含扩展的 C++ 代码的文件夹:

    g++ -std=c++11 hellopy.cpp -I/usr/include/python3.4 -I/usr/local/include/boost/python -lboost_python3  -o hello.so -shared -fPIC
    

    然后您可以将 hello 导入您的 python 环境。

    【讨论】:

      【解决方案4】:

      在 python 库中链接(例如,Linux 上的 -L/usr/lib/x86_64-linux-gnu -lpython2.7 或 CMake 中的 find_package(PythonLibs)1)将导致此链接器问题走开。

      下面是对该问题的更详细说明。在命令行上,

      $ nm --dynamic <path-to>/libboost_python.so | grep PyString_Size
      

      如果你觉得懒惰并假设你的 libboost_python 链接到 python2.7,只需运行这个

      $ nm --dynamic `locate libboost_python27.so | awk 'NR==1'` | grep PyString_Size
      

      你应该看到类似

      的东西
      U PyString_Size
      

      所以 PyString_Size 在 libboost_python27.so 中是未定义的 (U)。这就是链接器所抱怨的。我们已经证实了这一点。现在让我们在 libpython 中寻找这个符号。

      $ nm --dynamic `locate libpython2.7.so | awk 'NR==1'` | grep PyString_Size
      

      在我的机器上,我看到了这样的东西:

      00000000000f0530 T PyString_Size
      

      T 表示此符号的文本位于指定的地址。所以这证明除了 libboost_python 之外,我们没有在 libpython 中进行链接。

      1 你为什么不使用 CMake? :)

      【讨论】:

      • 对如何让 libboost_python 在 boost 构建期间与 libpython 静态链接有任何想法吗??