2017-07-15 69 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