最終更新
この質問はsetup.py
、Cのように、FORTRANコードに直接アクセスするcythonモジュールをコンパイルするaを作成する方法についてです。それは解決策へのかなり長く困難な旅でしたが、完全な混乱は文脈のために以下に含まれています。
元の質問
ヒープメモリを設定してFortranコードに渡すCythonファイルである拡張子と、可能であれば再実装を避けたい由緒ある古いモジュールであるFortranファイルがあります。
ファイルはCに正常にコンパイルされ.pyx
ますが、cythonコンパイラ.f90
は次のエラーでファイルをチョークします。
$ 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')
これが私のセットアップファイル(上半分)です:
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,
...
)
注:元々、Fortranファイルの場所が誤って指定されていました(ディレクトリプレフィックスなし)が、これを修正した後もまったく同じように壊れます。
私が試したこと:
私はこれを見つけて、次のようにFortranコンパイラ(つまりgfortran)の名前を渡してみました:
$ 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
そして、それが問題だった場合に備えて、私も削除しようとしまし--inplace
た(そうではありませんでした、一番上のエラーメッセージと同じです)。
では、このFortranをコンパイルするにはどうすればよいですか?それを自分自身にハックして.o
、リンクすることで逃げることはできますか?それとも、これはCythonのバグであり、distutilsを再実装したり、プリプロセッサをハックしたりする必要がありますか?
アップデート
それで、numpy.distutils
パッケージをチェックアウトしたので、私は問題をもう少し理解しました。あなたがしなければならないようです
- cythonを使用して.pyxファイルをcpython.cファイルに変換します。
- 次に、 'sのように、Fortranをサポートする
Extension
/の組み合わせを使用します。setup()
numpy
これを試した後、私のsetup.py
今は次のようになります:
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",
...
)
__init__.pyx
(一見許可されていないように見えるので、モジュールも少し再構築したことに注意してください...)
今、物事はバグが多く、プラットフォームに依存するようになります。2つのテストシステムを利用できます。1つはMacportsPython2.7を使用するMacOSX 10.6(Snow Leopard)で、もう1つはシステムpython2.7を使用するMacOS X 10.7(Lion)です。
Snow Leopardでは、以下が適用されます。
これは、モジュールがコンパイルされることを意味します(万歳!)(--inplace
numpyはないようですが、システム全体にテストモジュールをインストールする必要がありました:/)、それでも次のようにクラッシュしimport
ます:
>>> 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
そしてLionでは、かなり紛らわしい見た目のコンパイル行に続いて、コンパイルエラーが発生します。
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
ここで詳細を確認する前に、少し前に戻りましょう。まず、64ビットMacOSXのアーキテクチャの衝突については多くの頭痛の種があることを私は知っています。MacportsPythonをSnowLeopardマシンで動作させるために(システムpython 2.6からアップグレードするためだけに)非常に一生懸命働かなければなりませんでした。またgfortran -arch i686 -arch x86_64
、コンパイラに混合メッセージを送信していることを確認しました。そこにはあらゆる種類のプラットフォーム固有の問題が埋め込まれているため、この質問のコンテキストで心配する必要はありません。
しかし、この行を見てみましょう:
gfortran:f77: build/src.macosx-10.7-intel-2.7/delaunay/sphere-f2pywrappers.f
numpyは何をしているのですか?!このビルドではf2py機能は必要ありません!私は実際にf2pyの狂気に対処することを避けるためにcythonモジュールを作成しました(4つまたは5つの出力変数と、in-in-nor-out引数が必要です-どちらもf2pyでは十分にサポートされていません)。コンパイル.c
-> .o
、.f90
->.o
そしてそれらをリンクします。関連するすべてのヘッダーを含める方法を知っていれば、このコンパイラ行を自分で作成できます。
このために独自のmakefileを作成する必要はないことを教えてください...または、Fortranを(出力互換の)Cに変換する方法があるので、Pythonが.f90拡張子(全体を修正する)を見るのを避けることができます問題。)f2c
これはF77でのみ機能し、これはより新しい方言であるため、これには適していないことに注意してください(したがって.f90
ファイル拡張子)。
UPDATE 2 次のbashスクリプトは、コードを適切にコンパイルしてリンクします。
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
この種のハックをsetup.pyと互換性を持たせる方法について何かアドバイスはありますか?このモジュールをインストールしてPython.h
手動で検索する必要はありません...