4

そのような一般的なタイトルで申し訳ありませんが、私は正確に何が欠けているのか、何が間違っているのかよくわかりません。私の目的は、cygwinでboost.pythonを使用してPython拡張機能を構築し、bjamの代わりにmakeを使用するboost.buildツールを回避することです。後者の方法は私にとってはかなりうまくいきましたが、今はこの方法でやりたいと思っています。私はグーグルで同様のトピックを探すことで多くの問題を解決しました。それは私がいくつかのトリックを理解して前進するのに役立ちました。しかし、最後のステップでは、いくつかの問題があるようです。この投稿が将来他の人にも役立つことを願って、またセットアップをよりよく説明するために、すべてのステップを詳細に説明しようと思います。

pythonとboostの両方の元の(さまざまなcygwinリポジトリからの)インストールについてよくわからなかったので、ホームディレクトリに最初からインストールすることにしました。

  1. 最初にPythonをインストールします。これについての詳細はスキップします、それは多かれ少なかれ簡単です。後者の説明にとって重要なのはただの道です:

    /home/Alexey_2/Soft/python2.6-これはPYTHONPATHであり、PATHにも含まれています

  2. ブーストに取り組んでいます:

    a)ブーストソースを解凍します

    /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を呼び出すことができるようにします。ここと.bash_profileを今後編集するたびに、cygwinを再起動して変更を有効にします

    c)まだ

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

    ディレクトリ-user-config.jamを編集して、使用するPythonをbjamに知らせます。したがって、私の場合は1行だけ追加します。

    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-path(最後のエントリ)にlibpython2.6.dllが含まれているため、/ home / Alexey_2 / Soft / python2.6/binを配置します

    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. ライブラリパスが設定され、適切なライブラリに対してコンパイルされます(詳細:win7-64bitのmingwでboost.pythonを使用してコードをコンパイルします)。

  2. 上記のリンクは、user-config.jamを構成することが重要である理由を説明しています-私はステップ1cでそれを行いました。

  3. 起こりうる問題を回避するために(上記のリンクおよびboost.pythonをmingwとリンクできません(ただしmingwの場合))、静的に好きなboost.pythonライブラリを使用します

    link=shared 
    

    bjamへの引数として(1dを参照)

  4. ここで説明されているように:MinGW + Boost: `WSAStartup @ 8'へ の未定義の参照は、何かをコンパイルしたいライブラリをオブジェクトファイルの後にリストする必要があります。そのため、次のようになります。

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

最後に、問題に。上記の設定で、Python拡張オブジェクトファイルを正常にビルドできました。

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

期待されること(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つのタイプの中で)、私が最初にcygwinのLinuxエミュレーションスタイルから期待したように.soではありません。したがって、前の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
4

1 に答える 1

1

これImportErrorは通常、Boost.Pythonに関連していません。むしろ、それは通常、 Pythonモジュールの検索パスxyzにないことを示します。

これをデバッグするには、-vv引数を指定してpythonを実行することを検討してください。これにより、Pythonは、インポートしようとしたときにチェックされるファイルごとにメッセージを出力しますxyz。とにかく、ビルドプロセスは正しいように見えるので、問題はファイル拡張子またはモジュールが検索パスにないことが原因である可能性があります。

CygwinがPythonの実行時の読み込み動作とどのように相互作用するかについてはわかりません。でも:

  • Windowsでは、Python拡張機能に拡張機能があり.pydます。
  • Linuxでは、Python拡張機能に拡張機能があり.soます。

さらに、xyzライブラリが次のいずれかにあることを確認します。

  • test.pyスクリプトを含むディレクトリ(または現在のディレクトリ)。
  • PYTHONPATH環境変数にリストされているディレクトリ。
  • インストールに依存するデフォルトディレクトリ。

に示されている未解決のライブラリlddがエラーを引き起こす場合、通常、ImportError未定義の参照を示すメッセージとともに表示されます。

于 2013-03-22T17:54:12.903 に答える