[Numpy-discussion] Building f2py extensions on AMD64 with Python 2.7 Numpy 1.5, MSVC 2008 Pro and gfortran

Sturla Molden sturla at molden.no
Mon Aug 16 21:59:30 EDT 2010


> I don't really see how to make that works (that is running gfortran
> code in a spawned process), but if you know how to, please go ahead.


I didn't debug this code examples so there might be typos, but this is
just to illustrate the general idea:


Say we have a Fortran function with this interface:

subroutine foobar(m, n, x, y)
   integer :: m, n
   real*8 :: x(n), y(n)
end subroutine

We could then proceed like this:

We can create a chunk of uniquely named shared memory like this:

   tag = uuid.uuid4().hex
   size = 1 << 20 # 1 MiB from the paging file
   shm = mmap.mmap(0, size, tagname="Local\\%s"%(tag,))
   shm = np.frombuffer(shm, dtype=np.uint8)

The we use views of shm to set up x and y, e.g.

   m = 100
   n =  100
   nb = 8 * n * m
   x = shm[:nb].view(dtype=float).reshape((n,m))
   y = shm[nb:2*nb].view(dtype=float).reshape((n,m))

Then we can call a fortran program using subprocess module:

   returnval = subprocess.call(['foobar.exe','%d'%n, '%d'%m, tag])

Then we need some boilerplate C to grab the shared memory and call Fortran:

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>

/* fortran: pass pointers, append underscore */
extern void foobar_(int *m, int *n, double *x, double *y)

static int openshm(const char *tag, size_t size,
    HANDLE *phandle, void **pbuf)
{
    *phandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, TRUE, tag);
    if (!h) return -1;
    *pbuf = MapViewOfFile(*phandle, FILE_MAP_ALL_ACCESS, 0, 0, size);
    if (*pbuf == NULL) {
        CloseHandle(p);
        return -1;
    }
    return 0;
}

int main(int argc, char *argv[])
{
    char tag[256];
    HANDLE shmem;
    int m, n;
    double *x, *y;

    m = atoi(argv[1]);
    n = atoi(argv[2]);
    ZeroMemory(tag, sizeof(tag));
    sprintf(tag, "Local\\%s", argv[3]);

    /* get arrays from shared memory */
    if (openshm(tag, 2*m*n*sizeof(double), &shmem, &(void*)x)<0)
      return -1;
    y = x + m*n;

    /* call fortran */
    foobar_(&m, &n, x, y);

    /* done */
    CloseHandle(h);
    return 0;
}

Blah... ugly.

On Linux we could use os.fork instead of subprocess, and only y would need
to be placed in (anonymous) shared memory (due to copy-on-write). But on
the other hand, we don't have run-time issues with gfortran on Linux
either. Just to illustrate why Windows sucks sometimes.

:-)


Sturla











More information about the NumPy-Discussion mailing list