Verwenden von Cython zum Verknüpfen von Python mit einer gemeinsam genutzten Bibliothek

Lesezeit: 4 Minuten

Benutzeravatar von josephmisiti
Josephmisiti

Ich versuche, eine darin geschriebene Bibliothek eines Drittanbieters zu integrieren C Mit meinem python Anwendung verwenden Cython. Ich habe den gesamten Python-Code für einen Test geschrieben. Ich habe Probleme, ein Beispiel für die Einrichtung zu finden.

Ich habe ein pyd/pyx Datei, die ich manuell erstellt habe. Der Dritte hat mir eine gegeben header file (*.h) und ein shared library (*.so). Soweit ich das beurteilen kann, gibt es keine weiteren Abhängigkeiten. Kann jemand ein Beispiel geben, wie man dies mit Cython und disutils?

Vielen Dank

Benutzeravatar von Gauthier Boaglio
Gauthier Boaglio

Sicher !

(Im Folgenden gehe ich davon aus, dass Sie bereits wissen, wie man damit umgeht cimport und die Wechselwirkungen zwischen .pxd und .pyx. Wenn dies nicht vollständig der Fall ist, fragen Sie einfach und ich werde diesen Teil auch entwickeln.)

Das Beispiel (aus einem C++-Projekt von mir, aber ein C-Projekt würde ziemlich gleich funktionieren):

1. Die Setup-Datei von Distutils:

Angenommen, die zu erstellende Nebenstelle wird angerufen myext und die gemeinsam genutzte Bibliothek des Drittanbieters ist libexternlib.so (beachten Sie das 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/"]
             )
        ]
)           

Notiz : Ihre externe .so Datei wird über die verknüpft libraries Möglichkeit :

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

Beachten Sie das sources Option kann verwendet werden, um einige zusätzliche Quelldateien zu kompilieren.

Wichtig : myext.pxd (nicht verwechseln mit .pyd – Windows-Zeug) und myext.pyx sollte im selben Verzeichnis liegen. Zur Kompilierzeit wird die Definitionsdatei, falls vorhanden, zuerst verarbeitet (mehr).

2. Führen Sie es dann wie folgt aus:

Nachdem Sie das Verzeichnis in das geändert haben, das Ihre enthält myext.pxddein myext.pyxsowie 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 wird als Standort angenommen ./some/path/to/externlib/
  • yourheader.h wird als Standort angenommen ./some/path/to/includes/

Notiz : CFLAGS könnte auch mit eingerichtet worden sein extra_compile_args Möglichkeit :

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

Notiz : LDFLAGS könnte auch mit eingerichtet worden sein extra_link_args Möglichkeit :

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

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

3. Danach kann es losgehen:

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 Ihre neu erstellte Python-Erweiterung anhand ihres Namens importiert werden kann:

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

Notiz über Optimierung: Standardmäßig -O2 wird zum Kompilieren der Erweiterung verwendet, diese kann jedoch überladen werden (siehe oben Setup where -O3 angegeben).

Notiz über Cython-Pfade : Wenn Cython in einem benutzerdefinierten Verzeichnis installiert wurde, möchten Sie es vielleicht zuerst zu Ihrer Umgebung hinzufügen:

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

Nun, ich hoffe, ich habe die wichtigsten Punkte abgedeckt …

  • Hey, danke für all deine Hilfe. Ich erhalte die folgende Fehlermeldung: ld: Bibliothek nicht gefunden für -lMYLIB wobei MYLIB.so die Datei ist, mit der ich verlinken möchte – irgendwelche Ideen?

    – Josephmisiti

    8. Juni 2013 um 16:14 Uhr


  • Vergiss es, ich habe gerade gelesen, dass der Befehl gcc -l davon ausgeht, dass deiner *.so lib vorangestellt ist, also habe ich das entfernt und es hat es gefunden und scheint zu funktionieren.

    – Josephmisiti

    8. Juni 2013 um 16:37 Uhr

  • Freut mich das zu hören. Prost 😉

    – Gauthier Boaglio

    8. Juni 2013 um 17:21 Uhr

  • Sehr guter Code – außer was ist mit den nachgestellten Backslashes gegen Ende? Sie brauchen sie nicht (Sie stehen in Klammern) – im Allgemeinen brauchen Sie NIE nachgestellte Backslashes in richtigem Python (machen Sie es immer mit Klammern, geschweiften oder eckigen Klammern).

    – Tom Swirly

    3. Februar 2014 um 18:07 Uhr

  • @Dilawar Ich bin mir nicht sicher, was du mit “Versand” meinst. Sobald die Bibliothek freigegeben ist, besteht die einzige Anforderung darin, dass der Pfad ihres enthaltenden Ordners zur Umgebung hinzugefügt wird ($LD_LIBRARY_PATH und $PYTHONPATH– Siehe 3. Punkt der obigen Antwort). Verwenden Sie absolute Pfade und fügen Sie diese Exportbefehle zu Ihrer hinzu .profile oder .bashrc um es dauerhaft zu machen.

    – Gauthier Boaglio

    28. Februar 2014 um 10:10 Uhr


1395280cookie-checkVerwenden von Cython zum Verknüpfen von Python mit einer gemeinsam genutzten Bibliothek

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy