使用 distutils 在两个模块之间链接

发布于 2024-12-20 10:13:45 字数 2179 浏览 6 评论 0原文

我最近在使用几个已编译的 C++ 模块时暴露了一个问题,并且希望重新表述这个问题。

我有两个模块“mod1”和“mod2”。它们在我的 setup.py 中编译为两个不同的“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'])

但在内部,“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,就会出现段错误。


这两个模块都是作为共享库构建的 - 但如果我没记错的话,mod2 需要链接到 mod1 才能工作,因为它需要 mod1 中定义的内容。是否可以使用 setuptools/distribute 定义这样的依赖关系?

类似的东西:

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

从我的各种阅读来看,看起来可以使用 boost 的 bjam 实用程序执行类似的操作 - 不幸的是,我没有设法在我的系统上使用它(甚至编译示例)。

我尝试过的事情:

  • 将“mod1.cpp”添加到 mod2 的源中。它可以工作(有点:我必须在 mod2 之前导入 mod1 才能使其工作),但我失去了将模块作为共享对象的兴趣。

解决方法:

  • 将 mod1 作为 mod2 中的常规 python 模块导入,但这会在我的 C++ 代码中添加额外的 python 层,

您觉得怎么样?

I have recently exposed a problem when working with several compiled C++ modules and would like to rephrase the question.

I have two modules 'mod1' and 'mod2'. They are compiled as two distinct 'ext_modules' in my setup.py, as shown here :

#!/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'])

But internally, 'mod2.hpp' is including 'mod1.hpp', as the first module is defining stuff that is used by the second module.

EDIT : this will compile fine, but then :

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

Here, "Parent" is the name of a class defined in mod1 and used in mod2.

EDIT2 : another weird behaviour I don't understand :

gt; cd build/lib.linux-i686-2.7
gt; 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

Here, importing mod2 first fails. But if I try agin after importing mod1, I get a segfault.


Both modules are built as shared libraries - but if I'm not mistaken, mod2 needs to be linked to mod1 in order to work, as it needs stuff defined in mod1. Is it possible to define such a dependency with setuptools/distribute ?

Something like :

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

From my various readings, it looks like it is possible to do something like this with boost's bjam utility - unfortunately, I didn't manage to use it (even to compile the example) on my system.

Things I have tried:

  • adding 'mod1.cpp' to the sources of mod2. It works (kind of: I must import mod1 before mod2 to make it work) but I'm loosing the interest of having modules as shared objects.

Workarouds:

  • importing mod1 as a regular python module in mod2, but that would put an extra layer of python within my C++ code

What do you think ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

黯淡〆 2024-12-27 10:13:45

最后,我找不到如何使用 distutils/distribute 来做到这一点。所以我改用cmake,到目前为止它工作完美!

使用cmake,您可以轻松地将一个模块编译为共享库,然后将此共享库添加到另一个模块的依赖项中。

In the end, I could not find how to do that with distutils / distribute. So I switched to cmake, and so far it works flawlessly !

with cmake, you can easily compile one module as a shared library, and later add this shared library to the dependencies of another module.

二手情话 2024-12-27 10:13:45

如果你的mod2依赖于mod1,那么,在mod2之前显式导入mod1:

  • 当导入mod1时(使用dlopen()加载),
  • 当导入mod2时,mod1的所有符号都将被加载到内存中, dlopen() 将解析并使用已加载到内存中的符号

这只是一种替代方法:)

If your mod2 depend of mod1, then, import explicitely mod1 before mod2:

  • when mod1 will be imported (loaded with dlopen()), all symbols of mod1 will be loaded in memory
  • when mod2 will be imported, dlopen() will resolve and use symbol already loaded in memory

That's just an alternative :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文