分配一个共享库和一些C代码与用Cython扩展模块(Distributing a shared li

2019-07-29 21:20发布

我试图从一个大的C ++共享库(libbig.so)采取的一些功能,并通过用Cython揭露他们的Python的。 要做到这一点,我已经得到了周围提供从我所需要的共享库功能的简单封装,在某种程度上,可以很容易通过用Cython(pysmall.pyx)来调用一个小的C ++文件(small.cpp)。

libbig.so - > small.cpp,small.h - > libsmall.so - > pysmall.pyx - > pysmall.cpp - > pysmall.so

我可以构建和我自己的电脑上运行此扩展模块:我刚编入small.cpp libsmall.so,然后说:“图书馆= [‘小’]”在setup.py扩展对象来构建扩展模块pysmall 。所以。

现在我想发布这个扩展模块,和我有一个很难追查描述用于分发用Cython模块以及C源代码和共享库setup.py最佳实践资源。 我已经通过“阅读安装Python模块 ”,“ 发布Python模块 ”和“ 分发用Cython模块 ”。 我明白如何分配自身的扩展模块。 我即将发布的扩展模块的依赖关系的最佳途径少了一些。

在用Cython文件表明您应该包括生成的.cpp文件,还有.pyx文件,如果用Cython是不存在的,但它不提供代码,演示了如何最好地处理各种情况。 它也没有提到如何分配在其上用Cython模块所依赖的共享库。

我挖通过从熊猫,LXML,pyzmq,h5py的setup.py脚本等等,而且有相当多的外来工发生。 如果任何人有指针或示例代码可能会加速这一进程,我当然感激不尽!

Answer 1:

1)分发libbig.so

这是蟒蛇是不会帮助您解决问题。 你是谁定位? 如果是Linux,你可以要求他们与自己的包管理器安装呢? 如果libbig不通过包管理器进行分发或者它不是Linux和要定位多个架构,您可能需要分发libbig源。

2)用Cython / setuptools的。

坦率地说,我认为它最简单的,只是要求人们用Cython。 这种方式有代码的唯一一个地面实况版本,你不必担心不一致.pyx.cpp代码。 要做到这一点,最简单的方法是使用setuptools ,而不是distutils 。 这样一来,你可以使用:

setup('mypackage',
    ...
    install_requires=['cython'])

总之,你的setup.py脚本看起来像:

# setup.py

from setuptools import setup, Extension
from Cython.Distutils import build_ext

pysmall = Extension('pysmall',
    sources = ['pysmall.pyx', 'small.cpp'],
    include_dirs = ['include/'])

setup(name='mypackage',
      packages=['yourpurepythonpackage'],
      install_requires=['cython==0.17'],
      ext_modules=[pysmall],
      cmdclass = {'build_ext': build_ext})

如果你不喜欢,需要用Cython的想法,你可以这样做:

# setup.py

import warnings
try:
    from Cython.Distutils import build_ext
    from setuptools import setup, Extension
    HAVE_CYTHON = True
except ImportError as e:
    HAVE_CYTHON = False
    warnings.warn(e.message)
    from distutils.core import setup, Extension
    from distutils.command import build_ext

pysmall = Extension('pysmall',
    sources = ['pysmall.pyx', 'small.cpp'],
    include_dirs = ['include/'])

configuration = {'name': 'mypackage',
      'packages': ['yourpurepythonpackage'],
      'install_requires': ['cython==0.17'],
      'ext_modules': [pysmall],
      'cmdclass': {'build_ext': build_ext}}

if not HAVE_CYTHON:
    pysmall.sources[0] = 'pysmall.cpp'
    configuration.pop('install_requires')

setup(**configuration)


Answer 2:

这是我非常棘手的解决方案。 我们的想法是“隐藏”的存在cython ,直到它被要求安装。 这可以通过延迟计算来实现。 下面是一个例子:

from setuptools import setup, Extension

class lazy_cythonize(list):
    def __init__(self, callback):
        self._list, self.callback = None, callback
    def c_list(self):
        if self._list is None: self._list = self.callback()
        return self._list
    def __iter__(self):
        for e in self.c_list(): yield e
    def __getitem__(self, ii): return self.c_list()[ii]
    def __len__(self): return len(self.c_list())

def extensions():
    from Cython.Build import cythonize
    ext = Extension('native_ext_name', ['your/src/*.pyx'])
    return cythonize([ext])


configuration = {
    'name': 'mypackage',
    'packages': ['yourpurepythonpackage'],
    'install_requires': ['cython==0.17'],
    'ext_modules': lazy_cythonize(extensions)
}

setup(**configuration)

lazy_cythonize只有当有人试图访问它,产生它的内部元素假名单。
当它的需要,这个类进口Cython.Build并生成扩展名列表。 这避免了保留*.c文件在您的项目,需要用Cython当模块正在建设安装。

相当棘手,但实际上它的工作。



Answer 3:

我被推为修复setuptools的288 ,提名为发行作为setuptools的18.0。 这changelog的项目描述应当与建设工作的技术。 一个测试版可用于测试。



文章来源: Distributing a shared library and some C code with a Cython extension module