Cython und fortran - wie man ohne f2py zusammen kompiliert

ENDGÜLTIGES UPDATE

In dieser Frage geht es darum, wie man einesetup.py Dadurch wird ein Cython-Modul kompiliert, das wie C direkt auf FORTRAN-Code zugreift. Es war ein ziemlich langer und mühsamer Weg zur Lösung, aber das ganze Durcheinander ist unten für den Kontext aufgeführt.

URSPRÜNGLICHE FRAGE

Ich habe eine Erweiterung, die eine Cython-Datei ist, die einen Heap-Speicher einrichtet und ihn an den fortran-Code übergibt, und eine fortran-Datei, die ein ehrwürdiges altes Modul ist, das ich gerne vermeiden würde, wenn ich kann, neu zu implementieren.

Das.pyx Datei kompiliert gut zu C, aber der Cython-Compiler drosselt auf der.f90 Datei mit folgendem Fehler:

$ python setup.py build_ext --inplace
running build_ext
cythoning delaunay/__init__.pyx to delaunay/__init__.c
building 'delaunay' extension
error: unknown file type '.f90' (from 'delaunay/stripack.f90')

Hier ist (die obere Hälfte von) meiner Setup-Datei:

from distutils.core import setup, Extension
from Cython.Distutils import build_ext

ext_modules = [
  Extension("delaunay",
    sources=["delaunay/__init__.pyx",
             "delaunay/stripack.f90"])
]

setup(
  cmdclass = {'build_ext': build_ext},
  ext_modules = ext_modules,
  ...
)

ANMERKUNG: Ich hatte ursprünglich den Speicherort der fortran-Datei falsch angegeben (ohne das Verzeichnispräfix), aber dies bricht genauso ab, nachdem ich das behoben habe.

Dinge, die ich versucht habe:

ich fanddieseund haben versucht, den Namen des fortran-Compilers (d. h. gfortran) wie folgt einzugeben:

$ python setup.py config --fcompiler=gfortran build_ext --inplace
usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
   or: setup.py --help [cmd1 cmd2 ...]
   or: setup.py --help-commands
   or: setup.py cmd --help

error: option --fcompiler not recognized

Und ich habe auch versucht, zu entfernen--inplace, falls das das Problem war (es war nicht dasselbe wie die oberste Fehlermeldung).

Wie kompiliere ich dieses Fortran? Kann ich es in eine hacken?.o mich und mit dem Verlinken davonkommen? OderIst das ein Fehler in Cython?, was mich zwingt, distutils neu zu implementieren oder mit dem Präprozessor herumzuhacken?

AKTUALISIEREN

Also nach dem Auschecken dernumpy.distutils Pakete verstehe ich das Problem ein bisschen mehr. Es scheint, dass Sie müssen

Verwenden Sie Cython, um die .pyx-Dateien in Cpython .c-Dateien zu konvertieren.Dann benutze einExtension/setup() Kombination, die fortran unterstützt, wienumpy's.

Nachdem ich das versucht habe, meine Gütesetup.py sieht jetzt so aus:

from numpy.distutils.core import setup
from Cython.Build import cythonize
from numpy.distutils.extension import Extension

cy_modules = cythonize('delaunay/sphere.pyx')
e = cy_modules[0]

ext_modules = [
  Extension("delaunay.sphere",
      sources=e.sources + ['delaunay/stripack.f90'])
]

setup(
  ext_modules = ext_modules,
  name="delaunay",
  ...
)

(beachte, dass ich das Modul auch ein wenig umstrukturiert habe, da es anscheinend eine__init__.pyx ist nicht erlaubt ...)

Jetzt werden die Dinge fehlerhaft und plattformabhängig. Ich habe zwei Testsysteme zur Verfügung - ein Mac OS X 10.6 (Snow Leopard) mit Macports Python 2.7 und ein Mac OS X 10.7 (Lion) mit System Python 2.7.

Auf Snow Leopard gilt Folgendes:

Dies bedeutet, dass das Modul kompiliert (Hurra!) (Obwohl es keine gibt--inplace Für Numpy, so scheint es, musste ich das Testmodul systemweit installieren: /), aber ich bekomme immer noch einen Absturz aufimport wie folgt:

  >>> import delaunay
  Traceback (most recent call last):
    File "<input>", line 1, in <module>
    File "<snip>site-packages/delaunay/__init__.py", line 1, in <module>
      from sphere import delaunay_mesh
  ImportError: dlopen(<snip>site-packages/delaunay/sphere.so, 2): no suitable image found.  Did find:
    <snip>site-packages/delaunay/sphere.so: mach-o, but wrong architecture

und auf Lion erhalte ich einen Kompilierungsfehler, der einer ziemlich verwirrend aussehenden Kompilierungszeile folgt:

gfortran:f77: build/src.macosx-10.7-intel-2.7/delaunay/sphere-f2pywrappers.f
/usr/local/bin/gfortran -Wall -arch i686 -arch x86_64 -Wall -undefined dynamic_lookup -bundle build/temp.macosx-10.7-intel-2.7/delaunay/sphere.o build/temp.macosx-10.7-intel-2.7/build/src.macosx-10.7-intel-2.7/delaunay/spheremodule.o build/temp.macosx-10.7-intel-2.7/build/src.macosx-10.7-intel-2.7/fortranobject.o build/temp.macosx-10.7-intel-2.7/delaunay/stripack.o build/temp.macosx-10.7-intel-2.7/build/src.macosx-10.7-intel-2.7/delaunay/sphere-f2pywrappers.o -lgfortran -o build/lib.macosx-10.7-intel-2.7/delaunay/sphere.so
ld: duplicate symbol _initsphere in build/temp.macosx-10.7-intel-2.7/build/src.macosx-10.7-intel-2.7/delaunay/spheremodule.o ldand :build /temp.macosx-10.7-intelduplicate- 2.7symbol/ delaunay/sphere.o _initsphere in forbuild architecture /i386
temp.macosx-10.7-intel-2.7/build/src.macosx-10.7-intel-2.7/delaunay/spheremodule.o and build/temp.macosx-10.7-intel-2.7/delaunay/sphere.o for architecture x86_64

Lassen Sie uns jetzt einen Moment zurücktreten, bevor wir uns hier mit den Details befassen. Erstens weiß ich, dass Architekturkonflikte unter 64-Bit-Mac OS X Kopfzerbrechen bereiten. Ich musste sehr hart arbeiten, um Macports Python auf dem Snow Leopard-Computer zum Laufen zu bringen (nur um ein Upgrade von System Python 2.6 durchzuführen). Das weiß ich auch, wenn du es siehstgfortran -arch i686 -arch x86_64 Sie senden gemischte Nachrichten an Ihren Compiler. Dort stecken alle möglichen plattformspezifischen Probleme, über die wir uns im Zusammenhang mit dieser Frage keine Gedanken machen müssen.

Aber schauen wir uns nur diese Zeile an: gfortran:f77: build/src.macosx-10.7-intel-2.7/delaunay/sphere-f2pywrappers.f

Was macht Numpy ?! Ich benötige keine f2py-Funktionen in diesem Build! Ich habe tatsächlich ein Cython-Modul geschriebenum zu vermeiden Umgang mit dem Wahnsinn von f2py (Ich brauche 4 oder 5 Ausgangsvariablen sowie weder In- noch Out-Argumente - beides wird in f2py nicht gut unterstützt.) Ich möchte nur, dass es kompiliert wird.c ->.o, und.f90 ->.o und verknüpfe sie. Ich könnte diese Compiler-Zeile selbst schreiben, wenn ich wüsste, wie man alle relevanten Header einfügt.

Bitte sagen Sie mir, dass ich dafür kein eigenes Makefile schreiben muss ... oder dass es eine Möglichkeit gibt, fortran in (ausgangskompatibles) C zu übersetzen, damit Python die .f90-Erweiterung nie sieht (was das Ganze behebt) Problem.) Beachten Sie, dassf2c ist dafür nicht geeignet, da es nur auf F77 funktioniert und dies ein moderner Dialekt ist (daher das.f90 Dateierweiterung).

UPDATE 2 Das folgende Bash-Skript kompiliert und verknüpft den Code problemlos:

PYTHON_H_LOCATION="/opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7/"

cython sphere.pyx

gcc -arch x86_64 -c sphere.c -I$PYTHON_H_LOCATION
gfortran -arch x86_64 -c stripack.f90
gfortran -arch x86_64 -bundle -undefined dynamic_lookup -L/opt/local/lib *.o -o sphere.so

Irgendwelche Ratschläge, wie man diese Art von Hack mit einem setup.py kompatibel macht? Ich muss niemanden finden, der dieses Modul installiertPython.h manuell...

Antworten auf die Frage(3)

Ihre Antwort auf die Frage