2013-03-22 118 views
4

对不起,对于这样一个总体标题,但我不太确定我到底错过了什么或者我做错了什么。我的目标是在cygwin下使用boost.python构建一个python扩展,并避免使用boost.build工具,即使用make而不是bjam。后一种方式对我很好,但现在我想这样做。我通过Google搜索和寻找类似主题解决了许多问题,并帮助我找出一些技巧并前进。然而,在最后一步似乎存在一些问题。我会尽力在一些细节中描述我所有的步骤,希望这篇文章可能对未来的其他人有用,并且更好地描述设置。用boost.python手动构建cygwin中的python扩展

,因为我不是很肯定都蟒蛇的原(从各种Cygwin的仓库)安装并提高我决定从头我的主目录安装它们,所以这里是我做的:

  1. 先安装python。我将跳过这个细节,这是或多或少的直截了当。对于后面描述的重要仅仅是路径:

    /home/Alexey_2/Soft/python2.6 - 这是PYTHONPATH,也包括在PATH

  2. 升压工作:

    一)解压缩升压源到

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

    b)制作的bjam。首先进入目录:

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

    接下来,调用bootstrap.sh,最终在此目录中创建b2和bjam可执行文件。在.bash_profile中添加这个目录到PATH,所以我们可以调用bjam。这里后,我重新启动cygwin的.bash_profile中的每一个未来的编辑进行更改 前来效果

    C)仍然在

    /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. 建筑Python扩展。

    这里是我的简单测试程序(实际上的示例代码部分)

    // 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中的(最终),其中i定义环境变量:

# 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 

最后的问题。通过以上的设置,我是能够成功地建立了Python扩展对象文件:

xyz.so 

然而,当我通过简单的脚本来进行测试:

# this is a test.py script 
import xyz 

的导入错误说到:

$ 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) 

可能意味着。可能是我缺少的东西。但那是什么? 任何意见和建议(不只是关于最后一个问题)非常感谢。

编辑:

关注中(twsansbury)检查与-vv选项Python模块搜索路径的建议:

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,正如我最初从Cygwin的Linux仿真风格预期的那样。所以在之前的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很好解释了问题和研究工作。 – 2013-03-22 18:06:21

回答

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 2013-03-22 19:21:18