J'essaie d'intégrer une bibliothèque tierce écrite en C
avec mon application python
en utilisant Cython
. J'ai tout le code python écrit pour un test. J'ai du mal à trouver un exemple pour configurer cela.
J'ai un fichier pyd/pyx
Que j'ai créé manuellement. Le tiers m'a donné une header file (*.h)
et une shared library (*.so)
. Pour autant que je sache, il n'y a pas d'autres dépendances. Quelqu'un peut-il fournir un exemple de la façon de configurer cela à l'aide de Cython
et disutils
?
Merci
Sûr !
(Dans ce qui suit, je suppose que vous savez déjà comment gérer cimport
et les interactions entre .pxd
Et .pyx
. Si ce n'est pas complètement le cas, il suffit de demander et Je développerai également cette partie)
L'exemple (extrait d'un de mes projets C++, mais un projet C fonctionnerait à peu près de la même manière):
1. Le fichier d'installation de Distutils:
En supposant que l'extension à créer sera appelée myext
et que la bibliothèque partagée tierce est libexternlib.so
(Notez la lib * préfixe, ici) ...
# setup.py file
import sys
import os
import shutil
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
# clean previous build
for root, dirs, files in os.walk(".", topdown=False):
for name in files:
if (name.startswith("myext") and not(name.endswith(".pyx") or name.endswith(".pxd"))):
os.remove(os.path.join(root, name))
for name in dirs:
if (name == "build"):
shutil.rmtree(name)
# build "myext.so" python extension to be added to "PYTHONPATH" afterwards...
setup(
cmdclass = {'build_ext': build_ext},
ext_modules = [
Extension("myext",
sources=["myext.pyx",
"SomeAdditionalCppClass1.cpp",
"SomeAdditionalCppClass2.cpp"
],
libraries=["externlib"], # refers to "libexternlib.so"
language="c++", # remove this if C and not C++
extra_compile_args=["-fopenmp", "-O3"],
extra_link_args=["-DSOME_DEFINE_OPT",
"-L./some/extra/dependency/dir/"]
)
]
)
Remarque: Votre fichier externe .so
Est lié via l'option libraries
:
libraries=["externlib"] # Without the 'lib' prefix and the '.so' extension...
Remarque: l'option sources
peut être utilisée pour obtenir des fichiers source supplémentaires compilés.
Important: myext.pxd
(Ne pas confondre avec .pyd
- Windows) et myext.pyx
Devrait être dans le même répertoire. Au moment de la compilation, le fichier de définition, s'il existe, est traité en premier ( plus ).
2. Ensuite, exécutez-le comme suit:
Après avoir changé le répertoire en celui contenant votre myext.pxd
, Votre myext.pyx
, Ainsi que le script setup.py
Ci-dessus:
# setup.sh
# Make the "myext" Python Module ("myext.so")
CC="gcc" \
CXX="g++" \
CFLAGS="-I./some/path/to/includes/ -I../../../DEPENDENCIES/python2.7/inc -I../../../DEPENDENCIES/gsl-1.15" \
LDFLAGS="-L./some/path/to/externlib/" \
python setup.py build_ext --inplace
Où :
libexternlib.so
Est supposé être situé à ./some/path/to/externlib/
yourheader.h
Est supposé être situé à ./some/path/to/includes/
Remarque: CFLAGS
aurait également pu être configuré à l'aide de l'option extra_compile_args
:
extra_compile_args=["-I./some/path/to/includes/", "-fopenmp", "-O3"]
Remarque: LDFLAGS
aurait également pu être configuré à l'aide de l'option extra_link_args
:
extra_link_args=["-L./some/path/to/externlib/", "-DSOME_DEFINE_OPT", "-L./some/extra/dependency/dir/"]
Une fois distutils fait avec la construction, vous obtenez de nouveaux fichiers, spécialement le myext.cpp
, myext.h
Et surtout, le myext.so
.
3. Après cela, vous êtes prêt à partir:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./some/path/to/externlib/
export PYTHONPATH=$PYTHONPATH:./some/path/to/myext/
# Run some script requiring "myext.so"
python somescript.py
Où votre nouvelle extension Python extension peut être importée par son nom:
# somescript.py
import myext
from myext import PySomeFeature
...
Remarque sur l'optimisation: par défaut, -O2
Est utilisé pour compiler l'extension, mais cela peut être surchargé (voir la configuration ci-dessus où -O3
Est spécifié).
Remarque sur les chemins Cython: Si Cython a été installé dans un répertoire personnalisé, vous voudrez peut-être l'ajouter à votre environnement, avant tout:
PYTHONPATH=$PYTHONPATH:../../../DEPENDENCIES/Cython-0.18 export PYTHONPATH;
PATH=$PATH:../../../DEPENDENCIES/Cython-0.18/bin; export PATH;
Eh bien, j'espère avoir couvert les points principaux ...