Cython i fortran - jak się skompilować bez użycia f2py

KOŃCOWA AKTUALIZACJA

To pytanie dotyczy sposobu pisaniasetup.py który skompiluje moduł cythona, który uzyskuje bezpośredni dostęp do kodu FORTRAN, tak jak C. Była to dość długa i żmudna podróż do rozwiązania, ale cały bałagan jest zawarty poniżej dla kontekstu.

PYTANIE ORYGINALNE

Mam rozszerzenie, które jest plikiem Cythona, który ustawia pewną pamięć sterty i przekazuje ją do kodu fortran, oraz plik fortran, który jest czcigodnym starym modułem, którego chciałbym uniknąć, jeśli mogę.

The.pyx plik kompiluje się dobrze do C, ale kompilator Cythona dławi.f90 plik z następującym błędem:

$ 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')

Oto (górna połowa) mojego pliku instalacyjnego:

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

UWAGA: Początkowo lokalizacja pliku fortran była niepoprawnie określona (bez prefiksu katalogu), ale po tym, jak to naprawiłem, zostanie to przerwane dokładnie w ten sam sposób.

Rzeczy, które próbowałem:

znalazłemtoi próbowałem przekazać nazwę kompilatora fortran (tj. gfortran) w ten sposób:

$ 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

Próbowałem także usunąć--inplace, na wypadek, gdyby był to problem (nie był taki sam jak najwyższy komunikat o błędzie).

Jak więc skompilować to fortran? Czy mogę włamać się do.o ja i uciec z łączeniem go? Lubczy jest to błąd w Cythonie, co zmusi mnie do ponownego zaimplementowania distutils lub włamania się do preprocesora?

AKTUALIZACJA

Po sprawdzeniunumpy.distutils pakiety, rozumiem problem trochę bardziej. Wygląda na to, że musisz

Użyj cython do konwersji plików .pyx na pliki cpython .c,Następnie użyjExtension/setup() taka kombinacja, która obsługuje fortrannumpyjest.

Próbowałem tego, mójsetup.py teraz wygląda tak:

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",
  ...
)

(zauważ, że nieco zrestrukturyzowałem moduł, ponieważ pozornie jest__init__.pyx jest niedozwolone ...)

Teraz sprawy stają się błędne i zależne od platformy. Mam dwa systemy testowe - jeden Mac OS X 10.6 (Snow Leopard), używający Macports Python 2.7 i jeden Mac OS X 10.7 (Lion) z pytonem systemowym 2.7.

W systemie Snow Leopard obowiązuje:

Oznacza to, że moduł się kompiluje (hurra!) (Chociaż nie ma--inplace wydaje się, że dla numpy musiałem zainstalować system testujący w całym systemie: /), ale nadal mam awarięimport następująco:

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

i na Lionie dostaję błąd kompilacji, idąc za dość mylącą wyglądającą linią kompilacji:

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

Cofnijmy się teraz, zanim przejdziemy przez szczegóły tutaj. Po pierwsze, wiem, że w 64-bitowym systemie Mac OS X jest wiele problemów z konfliktami architektury; Musiałem bardzo ciężko pracować, aby Macports Python pracował na maszynie Snow Leopard (tylko w celu uaktualnienia z python systemowego 2.6). Wiem to także, kiedy widziszgfortran -arch i686 -arch x86_64 wysyłasz mieszane wiadomości do kompilatora. Istnieje wiele różnych specyficznych dla platformy problemów, w których nie musimy się martwić w kontekście tego pytania.

Ale spójrzmy tylko na tę linię: gfortran:f77: build/src.macosx-10.7-intel-2.7/delaunay/sphere-f2pywrappers.f

co robi numpy ?! W tej kompilacji nie potrzebuję żadnych funkcji f2py! Właściwie napisałem moduł cythonW celu uniknięcia radzenie sobie z niepoczytalnością f2py (muszę mieć 4 lub 5 zmiennych wyjściowych, jak również argumenty, które nie występują ani w tym, co nie ma - żaden z nich nie jest dobrze obsługiwany w f2py)..c ->.o, i.f90 ->.o i połącz je. Mógłbym napisać tę linię kompilatora osobiście, gdybym wiedział, jak dołączyć wszystkie odpowiednie nagłówki.

Powiedz mi, że nie muszę do tego pisać własnego pliku makefile ... lub że istnieje sposób na przetłumaczenie fortranu na (kompatybilny z wyjściem) C, więc mogę po prostu uniknąć pythona widzącego rozszerzenie .f90 (które naprawia całość problem.) Zauważ, żef2c nie nadaje się do tego, ponieważ działa tylko na F77 i jest to bardziej nowoczesny dialekt (stąd.f90 rozszerzenie pliku).

AKTUALIZACJA 2 Poniższy skrypt bashowy z przyjemnością skompiluje i połączy kod na miejscu:

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

Jakaś rada dotycząca tego, jak zrobić ten rodzaj hacku kompatybilnego z setup.py? Nie instaluję tego modułu, aby znaleźć goPython.h ręcznie...

questionAnswers(3)

yourAnswerToTheQuestion