web-dev-qa-db-fra.com

Utilisation de setuptools pour créer un package cython appelant une bibliothèque C externe

J'essaie de compiler, d'installer et d'exécuter un package que nous appellerons myPackage. Il contient un fichier *.pyx Qui appelle la fonction fftw_set_timelimit() de la bibliothèque fftw. Actuellement, lorsque j'exécute un script clientScript.py Qui importe le package, j'obtiens le message d'erreur suivant:

Traceback (most recent call last):
  File "clientScript.py", line 5, in <module>
    import myPackage.myModule
ImportError: /usr/local/lib/python2.7/dist-packages/myPackage/myModule.so: undefined symbol: fftw_set_timelimit

D'après ce que je comprends (je suis assez nouveau pour python et cython), la liaison avec la bibliothèque C n'est pas encore effectuée dans mon package. En effet, mon fichier setup.py Ressemble à ce :

from setuptools   import setup,find_packages
from Cython.Build import cythonize
import os

setup(
    name = "myPackage",
    version = "0.0.1",
    url = "none",
    author = "me",
    author_email = "[email protected]",
    packages=find_packages(),
    ext_modules = cythonize("pyClo/pyClo.pyx"),
)

Comme vous pouvez le voir, mon fichier setup.py Utilise setuptools. J'ai décidé de le faire car il est recommandé par le Python Packaging User Guide . Cependant, les instructions de la documentation Cython utilisent distutils à la place. La liaison des bibliothèques se fait via un appel à distutils.Extension('file',['file.pyx'],libraries='fftw'). Comment obtenir le même résultat en utilisant setuptools?

21
Gael Lorieul

Il s'avère que setuptools possède un module setuptools.extension.Extension Qui est utilisé de la même manière que le module distutils.extension.Extension.

Au final, le fichier setup.py Ressemble à quelque chose comme:

from setuptools import setup, find_packages
from setuptools.extension import Extension
from Cython.Build import cythonize

extensions = [
    Extension(
        "myPackage.myModule",
        ["myPackage/myModule.pyx"],
        include_dirs=['/some/path/to/include/'], # not needed for fftw unless it is installed in an unusual place
        libraries=['fftw3', 'fftw3f', 'fftw3l', 'fftw3_threads', 'fftw3f_threads', 'fftw3l_threads'],
        library_dirs=['/some/path/to/include/'], # not needed for fftw unless it is installed in an unusual place
    ),
]

setup(
    name = "myPackage",
    packages = find_packages(),
    ext_modules = cythonize(extensions)
)

Voici un aperçu de mon répertoire d'installation:

.
├── MANIFEST.in
├── myPackage
│   └── myModule.pyx
├── README.rst
└── setup.py

myModule.pyx est le fichier qui appelle fftw_set_timelimit().

MANIFEST.in Contient:

include myPackage/*.*

et README.rst est un simple fichier texte brut.

26
Gael Lorieul