2013-06-07 29 views
30

Sto cercando di integrare una libreria di terze parti scritta in C con la mia applicazione python utilizzando Cython. Ho scritto tutto il codice Python per un test. Sto riscontrando problemi nel trovare un esempio per l'impostazione.Utilizzo di Cython per collegare Python a una libreria condivisa

Ho un file pyd/pyx che ho creato manualmente. La terza parte mi ha dato un header file (*.h) e un shared library (*.so). Per quanto posso dire, non ci sono altre dipendenze. Qualcuno può fornire un esempio su come configurarlo usando Cython e disutils?

Grazie

risposta

48

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 ..

+0

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

+0

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

+0

Felice di sentirlo. Saluti ;-) –

Problemi correlati