如何在Python包中包含共享C库

MrL*_*eeh 7 python makefile setuptools

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

所以需要做的是:运行Makefile来编译库并将编译好的共享库(libhello.so此处称为)文件放在某个地方,可以从依赖Python包中访问它.

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

包目录的结构就像这样简单:

pkgtest/
  src/
     libhello.c
     libhello.h
     Makefile
  pkgtest/
    __init__.py
    hello.py
  setup.py
Run Code Online (Sandbox Code Playgroud)

我的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},
)
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

所以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()
Run Code Online (Sandbox Code Playgroud)

所以这实际上有效,但我不喜欢这种方法的是共享库存在于Python包的目录中.我认为将它放在某种中央库目录(例如/ usr/lib /)中会更好.但是对于这个,在安装时需要root权限.有人有这方面的经验,想分享一个解决方案或有用的想法.会很好.

ost*_*ach 6

您可以使用Manylinux创建一个包含共享库并适用于(几乎)任何 Linux 发行版的 Python 包。

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

一般程序是:

  1. 在 Manylinux 团队提供的 Docker 容器之一内构建外部库和 Python 包(请参阅python-manylinux-demo
  2. 运行auditwheel repair将包所依赖的外部共享库复制到Python Wheel中,并相应地设置RPATH。

有关示例,请参阅存储库中的.travis.yml和。build-wheels.shpython-manylinux-demo

  • 这看起来很棒。如果我做对了,该示例将展示如何构建 Python C 扩展并将其包含在轮子中。正如问题中所述,目标不是构建 Python C 扩展,而是构建并包含纯 C 共享库。我仍然不知道如何管理它。 (4认同)