如何在Python包中包含共享的C库 [英] How to include a shared C library in a Python package

查看:85
本文介绍了如何在Python包中包含共享的C库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个依赖于共享库的项目.从一开始就明确说明:共享库是纯C库,而不是Python库.为简单起见,我创建了一个名为 pkgtest 的小型演示项目.

I have a project depending on a shared library. To make it clear from the beginning: the shared library is a pure C library and not a Python library. For reasons of simplicity I created a small demo project called pkgtest which I will refer to.

因此,需要做的是:运行Makefile来编译库,然后将编译后的共享库文件(在此处称为libhello.so)放置在可以从依赖的Python包中访问的位置.

So what needs to be done is: Run a Makefile to compile the library and place the compiled shared library (called libhello.so here) file somewhere it can be accessed from within the depending Python package.

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

My best guess so far was to run the makefile as a preinstallation routine, copy the libhello.so file in the packages directory and add it to the package_data parameter of the setup script. When installed the shared library then gets placed in the site-packages/pkgtest/ directory and can be accessed from the module.

包目录的结构就是这样简单

The package directory is structure is as simple as this:

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

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

My setup.py looks like this:

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软件包的目录中.

The Makefile actually builds the library and copies it into the directory of my python package.

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函数,该函数将打印一些文本.但是为了完整起见,我将在此处显示代码:

So all hello.py is actually doing is load the library and call the hello function that prints some text. But for completeness I will show the code here:

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特权.是否有人对这种问题有一定的经验,并希望分享解决方案或有用的想法.会很棒.

So this actually works but what I don't like about this approach is that the shared library lives in the directory of the Python package. I figure it would be better to put it in some sort of central library directory such as /usr/lib/. But for this one would need root privileges on installation. Has somebody got some experience with this kind of problem and would like to share a solution or helpful idea. Would be great.

推荐答案

您可以使用

manylinux项目的目标是提供一种方便的方法来分发二进制Python扩展作为Linux上的轮子.这项工作已经产生了 PEP 513 ,它定义了manylinux1_x86_64平台代码.

The goal of the manylinux project is to provide a convenient way to distribute binary Python extensions as wheels on Linux. This effort has produced PEP 513 which defines the manylinux1_x86_64 and manylinux1_i686 platform tags.

一般步骤是:

  1. 在manylinux团队提供的一个Docker容器中构建外部库和Python包 (请参见 python-manylinux-demo )
  2. 运行 auditwheel repair 将包所依赖的外部共享库复制到Python滚轮,相应地设置RPATH.
  1. Build the external library and the Python package inside one of the docker containers provided by the manylinux team (see python-manylinux-demo)
  2. Run auditwheel repair to copy the external shared libraries that your package depends on into the Python wheel, setting the RPATH accordingly.

请参见 .travis.yml 和< build-wheels.sh >回购示例.

See .travis.yml and build-wheels.sh in the python-manylinux-demo repo for an example.

这篇关于如何在Python包中包含共享的C库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆