Sicuro!
(Di seguito, suppongo che sai già come affrontare cimport
e le interazioni tra .pxd
e .pyx
. Se questo non è completamente il caso, basta chiedere e io svilupperanno quella parte pure)
il campione (afferrato da un C++ mio progetto, ma un progetto C avrebbe funzionato più o meno lo stesso):
1. il file di installazione di Distutils:
Supponendo che l'estensione da creare saranno b e ha chiamato myext
e la biblioteca 3rd party condivisa è libexternlib.so
(notare il lib * prefisso, qui) ...
# 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/"]
)
]
)
Nota: tuo file esterno .so
è collegato tramite l'opzione libraries
:
libraries=["externlib"] # Without the 'lib' prefix and the '.so' extension...
Nota: l'opzione sources
può essere utilizzata per ottenere alcuni file di origine aggiuntivi compilati.
Importante:myext.pxd
(non confondere con .pyd
- roba di Windows) e myext.pyx
dovrebbe essere nella stessa directory. Al momento della compilazione il file di definizione, se esiste, viene elaborato per primo (more).
2.Quindi eseguirlo nel modo seguente:
Dopo aver cambiato directory a quella contenente il myext.pxd
, il vostro myext.pyx
, così come sopra setup.py
script:
# 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
Dove:
libexternlib.so
è si presume che si trovi a ./some/path/to/externlib/
yourheader.h
si presume sia situato a ./some/path/to/includes/
Nota: CFLAGS
potrebbe anche essere stato configurazione utilizzando l'opzione extra_compile_args
:
extra_compile_args=["-I./some/path/to/includes/", "-fopenmp", "-O3"]
Nota: LDFLAGS
potrebbe anche essere stato configurazione utilizzando l'opzione extra_link_args
:
extra_link_args=["-L./some/path/to/externlib/", "-DSOME_DEFINE_OPT", "-L./some/extra/dependency/dir/"]
Una volta eseguite le distutils con la build, ottieni alcuni nuovi file, specialmente lo myext.cpp
, myext.h
e, soprattutto, lo myext.so
.
3. Dopo di che, si sta bene ad andare:
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
Dove l'estensione Python appena creato può essere importato con il suo nome:
# somescript.py
import myext
from myext import PySomeFeature
...
Nota di ottimizzazione : Per impostazione predefinita, -O2
viene utilizzato per compilare l'estensione, ma questo può essere sovraccarico (vedere l'impostazione precedente in cui è specificato -O3
).
Nota sui percorsi Cython: Se Cython è stato installato in una directory personalizzata, si potrebbe desiderare di aggiungerlo al vostro ambiente, prima di tutto:
PYTHONPATH=$PYTHONPATH:../../../DEPENDENCIES/Cython-0.18 export PYTHONPATH;
PATH=$PATH:../../../DEPENDENCIES/Cython-0.18/bin; export PATH;
Beh, spero ho coperto i punti principali ..
Ehi, grazie per tutto il tuo aiuto. Sto ottenendo il seguente errore: ld: libreria non trovata per -lMYLIB dove MYLIB.so è il file che sto cercando di collegare - qualche idea? – josephmisiti
dimenticalo, ho appena letto che il comando gcc -l presuppone che il tuo * .so sia preceduto da lib, quindi l'ho rimosso e l'ho trovato e sembra funzionare. – josephmisiti
Felice di sentirlo. Saluti ;-) –