f2py: questions on array arguments
Ramon Crehuet skrev:
1. The follwing fortran function:
function f2(x,y) implicit none real,intent(in):: x,y real, dimension(3):: f2 f2(1)=x+y**2 f2(2)=sin(x*y) f2(3)=2*x-y end function f2
gives a segmentation fault when called from python if it is not in a fortran module. If it is contained in a fortran module, it works fine and returns an array. That makes sense because fortran modules automatically generate an interface. However, I don't see that reflected in the .pyf files generated by f2py. So, is there a way to "correct" the function outside the module to work with f2py?
Wrap it in a subroutine f2wrap(x,y,output) and call that. C and Fortran interpop (which is what f2py does) can only go so far. C has no concept of functions returning arrays. The Fortran function must know where to write the return values, but how can you provide that information from C? So Fortran and C has different calling conventions here. And the reason for this working inside a module is that f2py must write a Fortran wrapper for the module. With modules there are name mangling and stuff going on that are not interopable with C. But then you have a situation where f2 is called from Fortran, so it will not segfault.
2. I have read in several posts that automatic arrays do not work with f2py. So that something like:
real function trace(m) real, dimension(:,:), intent(in) :: m
Has to be converted into:
real function trace2(m,n) integer, intent(in) :: n !f2py integer,intent(hide),depend(m) :: n=shape(m,0) real, dimension(n,n), intent(in) :: m
Again, here you have a C vs. Fortran incompatibility again. An assume shaped array like "m" in "trace" is actually a dope vector, i.e. a C struct not different from NumPy's PyArrayObject (though the binary layout is compiler dependent, and incompatible with NumPy). So we cannot pass a C pointer to "trace" and hope that it will work. But if we do know the C defintion of the Fortran compiler's dope vector, we can fill in the fields from a PyArrayObject and pass a pointer to the struct (there is a C library that attempts to do that, but I don't recall the name). But in "trace2", the shape of "m" is explicit. Here Fortran will assume m is just a C pointer to the first element. Fortran 77 compilers usually treat explicit and assumed-ashed arrays differently for interopability with C and compatilibity with other F77 compilers. So in "trace2", we can pass a C pointer to the first element of "m", whereas in "trace" we cannot. This difference is not required by the standard though. A Fortran 90 compiler could use only dope vectors if it wanted to. (There are other non-standard ways of interfacing with C such as Cray pointers.) So this is a bit murky territory. With Fortran 2003 we finally have a portable Fortran to C interface. Not all Fortran compilers implement this; gfortran does, whereas my favourite compiler Absoft does not. Sturla
Ramon Crehuet skrev:
real function trace(m) !f2py integer,depend(m) :: n=shape(m,0) !f2py real, dimension(n,n), intent(in) :: m real, dimension(:,:), intent(in) :: m
But it does not work. Is there a workaround to avoid passing the dimension of the matrix as a fortran argument? If you know your compiler's "dope vector" (known for most compilers, or just ask the vendor), we could implement an ndarray to Fortran 90 array converter in C, and pass a pointer to a dope vector struct.
If you don't know this, you will need a Fortran wrapper/proxy function. There are several ways that could work: Either: - Pass in all information about the array (shape and strides), then pass on a Fortran pointer or a slice. Or: - A C utility function could expose the PyArrayObject fields to Fortran. - The Fortran compiler might support C structures as an extension (e.g. Absoft). - Fortran 2003 ISO C bindings: C structures are supported. After the ndarray's meta-information is obtained, from any of those three, you can: - Use non-standard Cray pointers to access the buffer. - Use Fortran 2003 ISO C bindings to access the buffer: c_f_pointer converts a C pointer to a Fortran pointer. There is actually a Cython-related project called 'fwrap' that works somewhat like this. But if you have a Fortran contiguous array, or can create one, f2py will mean much less work. Sturla
participants (2)
-
Ramon Crehuet
-
Sturla Molden