如何在Python包中包含共享的C库 [英] How to include a shared C library in a Python package
问题描述
我有一个依赖于共享库的项目.从一开始就明确说明:共享库是纯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 ,它定义了 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
和
manylinux1_x86_64
and manylinux1_i686
platform tags.
auditwheel repair
将包所依赖的外部共享库复制到Python滚轮,相应地设置RPATH.
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屋!