【问题标题】:setuptools: build shared library from C++ code, then build Cython wrapper linked to shared librarysetuptools:从 C++ 代码构建共享库,然后构建链接到共享库的 Cython 包装器
【发布时间】:2018-08-22 06:57:03
【问题描述】:

我们有一堆 C++ 文件,其中包含我们使用 Cython 包装到 Python 的类。我们使用 setuptools 来构建 Cython 扩展。这一切都很好,我们按照这里的指南进行操作: http://cython.readthedocs.io/en/latest/src/userguide/wrapping_CPlusPlus.html

我们基本上是在做这样的事情

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize(
           "rect.pyx",                 # our Cython source
           sources=["Rectangle.cpp"],  # additional source file(s)
           language="c++",             # generate C++ code
      ))

我们不喜欢我们必须重新编译所有内容,即使只有 Cython 部分发生更改,在此示例中为 rect.pyx。事实上,我们从不接触.cpp 文件,但经常更改.pyx 文件。

我们想将.cpp文件单独编译成静态或共享库,然后独立构建.pyx文件,链接到.cpp文件生成的库。使用makecmake,这一切都将变得简单,但我们需要一个仅使用setuptools 的纯Python 解决方案。模拟代码看起来像这样:

from distutils.core import setup
from Cython.Build import cythonize

class CppLibary:
    # somehow get that to work

# this should only recompile cpplib when source files changed
cpplib = CppLibary('cpplib',
                   sources=["Rectangle.cpp"], # put static cpp code here
                   include_dirs=["include"])

setup(ext_modules = cythonize(
           "rect.pyx",                 # our Cython source
           libraries=[cpplib],         # link to cpplib
           language="c++",             # generate C++ code
      ))

【问题讨论】:

标签: python c++ build cython setuptools


【解决方案1】:

setup 有一个看似未记录的功能可以做到这一点,例如:

import os

from setuptools import setup
from Cython.Build import cythonize

ext_lib_path = 'rectangle'
include_dir = os.path.join(ext_lib_path, 'include')

sources = ['Rectangle.cpp']

# Use as macros = [('<DEFINITION>', '<VALUE>')]
# where value can be None
macros = None

ext_libraries = [['rectangle', {
               'sources': [os.path.join(ext_lib_path, src) for src in sources],
               'include_dirs': [include_dir],
               'macros': macros,
               }
]]

extensions = [Extension("rect",
              sources=["rect.pyx"],
              language="c++",
              include_dirs=[include_dir],
              libraries=['rectangle'],
)]

setup(ext_modules=cythonize(extensions),
      libraries=ext_libraries)

libraries 参数构建在目录rectangle 中找到的外部库,包含目录rectangle/include 在它和扩展之间是公共的。

还将导入从已弃用的 distutils 切换到 setuptools,现在是 setuptools 的一部分。

尚未看到有关此参数的任何文档,但看到它在其他项目中使用。

这是未经测试的,如果不起作用,请提供示例文件进行测试。

【讨论】:

  • 感谢您的指点,这很有帮助。我试图按照您的示例进行操作,但它不起作用。 ext_libraries 不是由 setuptools 编译的,只有 Cython 扩展。我收到这样的错误ld: library not found for -llibrectangle
  • 您可能需要手动将生成的rectangle 对象文件作为extra_objects 参数包含到扩展中,因为共享对象不会安装在任何地方以供链接器查找。是否生成了对象,或者根本没有为rectangle 构建任何东西?如上所述,需要显示完整的代码进行测试,请参阅MCVE。请注意,ext_libraries 的类型应为 list(list(str, dict))) - 答案已更新。
  • 对于其他对此感到困惑的人:python setup.py develop 不会自动构建 clib。您需要手动执行一次python setup.py build_clib
猜你喜欢
  • 2012-05-31
  • 2016-08-01
  • 2012-03-20
  • 1970-01-01
  • 2017-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-03
相关资源
最近更新 更多