1

最近、いくつかのコンパイル済み C++ モジュールを操作するときに問題が発生したため、質問を言い換えたいと思います。

「mod1」と「mod2」の 2 つのモジュールがあります。ここに示すように、setup.py で 2 つの異なる「ext_modules」としてコンパイルされます。

#!/usr/bin/python2

from setuptools import setup, Extension

mod1 = Extension('mod1',
                 sources = ['mod1.cpp'],
                 libraries = ['boost_python'])

mod2 = Extension('mod2',
                 sources = ['mod2.cpp'],
                 libraries = ['boost_python'])

setup(name='foo',
      version='0.0',
      description='',
      ext_modules=[mod1,mod2],
      install_requires=['distribute'])

しかし、内部では、最初のモジュールが 2 番目のモジュールで使用されるものを定義しているため、'mod2.hpp' は 'mod1.hpp' を含んでいます。

編集:これは正常にコンパイルされますが、その後:

$> cd build/lib.linux-i686-2.7
$> python2 -c "import mod1 ; import mod2"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: ./mod2.so: undefined symbol: _ZN6ParentD2Ev

ここで、「Parent」は mod1 で定義され、mod2 で使用されるクラスの名前です。

EDIT2:私が理解していない別の奇妙な動作:

$> cd build/lib.linux-i686-2.7
$> python2
Python 2.7.2 (default, Nov 21 2011, 17:24:32) 
[GCC 4.6.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import mod2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: ./mod2.so: undefined symbol: _ZN6ParentD2Ev
>>> import mod1
>>> import mod2
Segmentation fault

ここでは、最初に mod2 をインポートすると失敗します。しかし、mod1 をインポートした後で agin を実行すると、segfault が発生します。


どちらのモジュールも共有ライブラリとして構築されていますが、私の間違いでなければ、mod1 で定義されたものが必要なため、mod2 を機能させるには mod1 にリンクする必要があります。setuptools/distribute でそのような依存関係を定義することは可能ですか?

何かのようなもの :

mod2 = Extension('mod2',
                 sources = ['mod2.cpp'],
                 libraries = ['boost_python',mod1])

私のさまざまな読書から、ブーストの bjam ユーティリティでこのようなことを行うことが可能であるように見えます.

私が試したこと:

  • mod2 のソースに「mod1.cpp」を追加します。それは機能します(一種:機能させるにはmod2の前にmod1をインポートする必要があります)が、モジュールを共有オブジェクトとして持つことへの関心を失っています。

回避策:

  • mod1をmod2の通常のpythonモジュールとしてインポートしますが、それは私のC ++コード内に余分なpythonの層を置きます

どう思いますか ?

4

2 に答える 2

1

結局、distutils/distributeでそれを行う方法を見つけることができませんでした。それで私はcmakeに切り替えました、そして今のところそれは完璧に動作します!

cmakeを使用すると、1つのモジュールを共有ライブラリとして簡単にコンパイルし、後でこの共有ライブラリを別のモジュールの依存関係に追加できます。

于 2011-12-15T21:28:23.467 に答える
0

mod2 が mod1 に依存している場合は、明示的に mod1 を mod2 の前にインポートします。

  • mod1 がインポート (でロードdlopen()) されると、mod1 のすべてのシンボルがメモリにロードされます。
  • mod2 がインポートされると、dlopen()解決され、メモリに既に読み込まれているシンボルが使用されます

それは単なる代替手段です:)

于 2011-12-10T14:22:11.167 に答える