如何使用Cython和iso_c_bindings在python中使用fortran90子例程

时间:2013-01-18 19:37:57

标签: python-2.7 fortran90 f2py

直到最近,我一直在使用IDL来解决我的大多数计算问题。我最常用的例程之一是一些fortran90代码,用C语言包装并使用CALL_EXTERNAL函数从IDL调用(没有一个由我编写)。出于各种原因,我将大部分计算转移到Python,但我还没有找到合并fortran代码的好方法。似乎F2PY是最明显的方式,但实际上生成的模块似乎非常不稳定。

基本上我想知道是否有更好的方法来解决这个问题。看起来重写现有的C包装器和Cython来使用Python的代码应该相对简单,虽然我不得不承认我完全不了解C / Cython并且对python来说很新,所以任何帮助都会非常感激。

作为参考,我在下面包含了现有的C包装器:

#include <stdio.h>

void bvls(int argc, void *argv[]) {

extern void bvls_(); 
int *n, *m, *nsetp, *index, *ierr;     
double **a, **b, **bnd, **w, **x;   
double *rnorm;

a =     (double **) argv[0];
m =     (int *)     argv[1];
n =     (int *)     argv[2];
b =     (double **) argv[3];
bnd =   (double **) argv[4];
x =     (double **) argv[5];
rnorm = (double *)  argv[6];
nsetp = (int *)     argv[7];
w =     (double **) argv[8];
index = (int *)     argv[9];
ierr =  (int *)     argv[10];

bvls_(a,m,n,b,bnd,x,rnorm,nsetp,w,index,ierr); 

}

编辑:在向其他人提及之后,他们建议也应该可以使用fortran ISO_C_BINDINGS模块直接与Cython接口,绕过对中间C包装器的需求。

1 个答案:

答案 0 :(得分:0)

您当前使用的C包装器不适合暴露给Python。您可能希望在Python中使用函数签名来镜像Fortran签名,而不是现有C包装器的尴尬签名。

无论是保留C包装还是使Fortran函数C与ISO_C_BINDINGS可互操作,最终与Cython的接口无关紧要。您只需要知道要公开的库中C函数的签名。

无论哪种方式,这都是遵循Interfacing with External C Code的Cython教程的简单案例,让Cython知道您想要公开的函数的签名。假设您要镜像Fortran签名,它将如下所示:

cdef extern from "bvls.h":
    void bvls(double* a, int m, int n, double* b, double* bnd, double* x,
              double rnorm, int nsetp, double* w, int index, int ierr)

然后,直接创建一个从Python调用的惯用函数。您可能希望允许调用者为所有double*参数传入NumPy数组:

cimport numpy as np

def pybvls(a, int m, int n, b, bnd, x, double rnorm,
           int nsetp, w, int index, int ierr):
    cdef double *a_, *b_, *bnd_, *x_, *w_
    # Get the raw data pointers from NumPy arrays
    a_ = <double *>np.PyArray_DATA(a)
    b_ = <double *>np.PyArray_DATA(b)
    bnd_ = <double *>np.PyArray_DATA(bnd)
    x_ = <double *>np.PyArray_DATA(x)
    w_ = <double *>np.PyArray_DATA(w)
    bvls(a_, m, n, b_, bnd_, x_, rnorm, nsetp, w_, index, ierr)

最后,您可能希望编写为setup.py文件,以便使用distutils为您构建扩展模块,如the Cython documentation中所述。