2013-06-07 3 views
30

Ich versuche, eine Bibliothek von Drittanbietern in C mit meiner python Anwendung mit Cython integriert zu integrieren. Ich habe den gesamten Python-Code für einen Test geschrieben. Ich habe Probleme, ein Beispiel für die Einrichtung zu finden.Verwenden von Cython zum Verknüpfen von Python mit einer freigegebenen Bibliothek

Ich habe eine pyd/pyx Datei, die ich manuell erstellt habe. Die dritte Partei hat mir eine header file (*.h) und eine shared library (*.so) gegeben. Soweit ich das beurteilen kann, gibt es keine weiteren Abhängigkeiten. Kann jemand ein Beispiel dafür geben, wie man das unter Verwendung von Cython und disutils einrichtet?

Danke

Antwort

48

Sicher!

(Im Folgenden gehe ich davon aus, dass Sie bereits wissen, wie mit cimport und die Wechselwirkungen zwischen .pxd und .pyx zu behandeln. Ist dies nicht ganz der Fall ist, fragen Sie einfach und ich werde diesen Teil auch entwickeln)

die Probe (aus einem C++ Projekt von mir nahm, sondern ein C-Projekt funktionieren würde so ziemlich das gleiche):

1. die Distutils Setup-Datei:

Unter der Annahme, dass die Erweiterung geschaffen werden will b e genannt myext und die dritte Partei gemeinsam genutzte Bibliothek ist libexternlib.so (man beachte den lib * Präfix hier) ...

# 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/"] 
      ) 
     ] 
)   

Hinweis: Ihre externe .so Datei über die libraries Option verknüpft ist:

libraries=["externlib"] # Without the 'lib' prefix and the '.so' extension... 

Hinweis: Die Option sources kann verwendet werden, um zusätzliche Quelldateien zu kompilieren.

Wichtig:myext.pxd (nicht zu verwechseln mit .pyd - Windows-Material) und myext.pyx im selben Verzeichnis sein sollte. Zur Kompilierungszeit wird die Definitionsdatei, falls sie existiert, zuerst verarbeitet (more).

2.Dann ist es läuft wie folgt:

Nach geändertenem Verzeichnis auf das mit mit Ihrem myext.pxd, Ihrem myext.pyx, sowie der oben setup.py Skript:

# 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 

Wo:

  • libexternlib.so ist angenommen, um ./some/path/to/externlib/
  • yourheader.h befindet sich bei 0 befindet

Hinweis: CFLAGS auch Setup hätte die extra_compile_args Option:

extra_compile_args=["-I./some/path/to/includes/", "-fopenmp", "-O3"] 

Hinweis: LDFLAGS auch Setup hätte die extra_link_args Option:

extra_link_args=["-L./some/path/to/externlib/", "-DSOME_DEFINE_OPT", "-L./some/extra/dependency/dir/"] 

Sobald distutils mit dem Build fertig ist, Sie erhalten einige neue Dateien, speziell die myext.cpp, myext.h und vor allem die myext.so.

3. Danach sind Sie gut zu gehen:

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 

Wo Ihr frisch Python erstellt Erweiterung durch seinen Namen importiert werden können:

# somescript.py 
import myext 
from myext import PySomeFeature 
... 

Hinweis über Optimierung : Standardmäßig wird -O2 zum Kompilieren der Erweiterung verwendet, aber dies kann überlastet werden (siehe oben Setup, wobei -O3 angegeben ist).

Hinweis über Cython Pfade: Wenn Cython in einem benutzerdefinierten Verzeichnis installiert wurde, könnte man es zu Ihrer Umgebung hinzufügen möchten, vor allem:

PYTHONPATH=$PYTHONPATH:../../../DEPENDENCIES/Cython-0.18 export PYTHONPATH; 
PATH=$PATH:../../../DEPENDENCIES/Cython-0.18/bin; export PATH; 

Nun hoffe ich, dass die wichtigsten Punkte ..

+0

Hey, Danke für deine Hilfe. Ich erhalte den folgenden Fehler: ld: Bibliothek nicht gefunden für -lMYLIB wo MYLIB.so ist die Datei, gegen die ich versuche zu verknüpfen - irgendwelche Ideen? – josephmisiti

+0

Vergiss es, ich habe gerade gelesen, dass der gcc -l-Befehl davon ausgeht, dass dein * .so mit lib vorankommt, also habe ich das entfernt und es gefunden und scheint zu funktionieren. – josephmisiti

+0

Froh, das zu hören. Prost ;-) –