2017-07-15 72 views
3

我有一个项目取决于共享库。为了从头开始说明:共享库是一个纯粹的C库,而不是一个Python库。为了简单起见,我创建了一个名为pkgtest的小型演示项目,我将参考它。如何在Python包中包含共享C库

所以需要做的是:运行一个Makefile来编译库,并将编译后的共享库(在此称为libhello.so)文件放置在某个可从取决于的Python包中访问的位置。

我最好的猜测,到目前为止是运行makefile作为一个预安装程序中,libhello.so文件复制在包目录,并将其添加到安装脚本的package_data参数。安装后,共享库将被置于site-packages/pkgtest/目录中,并可通过该模块进行访问。

包目录结构是如此简单:

pkgtest/ 
    src/ 
    libhello.c 
    libhello.h 
    Makefile 
    pkgtest/ 
    __init__.py 
    hello.py 
    setup.py 

我setup.py看起来是这样的:

setup.py

import subprocess 
from setuptools import setup 
from distutils.command.install import install as _install 


class install(_install): 
    def run(self): 
     subprocess.call(['make', 'clean', '-C', 'src']) 
     subprocess.call(['make', '-C', 'src']) 
     _install.run(self) 


setup(
    name='pkgtest', 
    version='0.0.1', 
    author='stefan', 
    packages=['pkgtest'], 
    package_data={'pkgtest': ['libhello.so']}, 
    cmdclass={'install': install}, 
) 

Makefile的实际编制该库并将其复制到我的python包的目录中。

的src/Makefile文件

all: libhello.so 

libhello.o: libhello.c 
     gcc -fPIC -Wall -g -c libhello.c 

libhello.so: libhello.o 
     gcc -shared -fPIC -o libhello.so libhello.o 
     cp libhello.so ../pkgtest/libhello.so 

clean: 
     rm -f *.o *.so 

因此,所有hello.py实际上正在做的是加载库并调用hello功能,打印一些文字。但对于完整性,我将在这里展示的代码:

pkgtest/hello.py

import os 
import ctypes 

basedir = os.path.abspath(os.path.dirname(__file__)) 
libpath = os.path.join(basedir, 'libhello.so') 

dll = ctypes.CDLL(libpath) 

def say_hello(): 
    dll.hello() 

所以这实际上是工作,但我不喜欢这种方式就是共享库生活在Python包的目录。我认为最好将它放在某种中央库目录中,例如/usr/lib/。但是,对于这个需要安装时的root权限。有人有这种问题的一些经验,并希望分享一个解决方案或有用的想法。会很好。

+0

你有没有考虑过像[conda](https://conda.io/miniconda.html)这样的软件包管理器?您可以为您的库和Python代码创建一个单独的包,并将该库指定为'meta.yaml'文件中Python代码的依赖关系。 – ostrokach

+0

我没有想过conda,但。你是对的,这肯定是一个选择,但不是我的第一选择,因为我希望这个软件包可以通过'pip install ...'来使用。 – MrLeeh

+0

在这种情况下,我不认为你的python包文件夹中有一个编译的库文件是一个问题。这就是[Python扩展模块](https://docs.python.org/3/extending/building.html)和[Cython](http://docs.cython.org/en/latest/index.html)模块摆放在。但也许有更好的解决方案... – ostrokach

回答

2

您可以创建一个包含共享库的Python包,它可以在几乎所有使用manylinux的Linux发行版上运行。

manylinux项目的目标是提供一种方便的方式将二进制Python扩展作为轮子分布在Linux上。这项工作产生了PEP 513,它定义了manylinux1_x86_64manylinux1_i686平台标签。

的一般程序是:

  1. 构建外部库和Python包内由manylinux队 提供的泊坞窗容器之一(见python-manylinux-demo
  2. 运行auditwheel repair复制的外部您的软件包依赖的共享库放入Python滚轮,相应地设置RPATH。

参见.travis.ymlbuild-wheels.shpython-manylinux-demo回购的一个例子。

+0

这看起来不错。如果我明白了,这个例子展示了如何构建一个Python C扩展并将其包含在内。正如问题中所述,目标不是构建Python C扩展,而是构建并包含纯C的共享库。我仍然无法弄清楚如何管理它。 – MrLeeh