Return double array through FORTRAN (DLL) to process further in python

0

I have been struggling with this issue for a while now, and search queries / applicable documentation did not yield any viable results either; hence posting it here.

What do I want to accomplish:

  • I have some program written in FORTRAN77 which takes some arguments and returning a double precision array of fixed length.
  • I wish to use another programming language to call this function (for now I use python for testing purposes; but this will be subject to change - so f2py isn't an option here)

The FORTRAN routine can be summarized to be something as follows:

      FUNCTION TST (IIN)
      IMPLICIT LOGICAL (A-Z)
cGCC$ ATTRIBUTES DLLEXPORT, STDCALL :: TST
      INTEGER           II,IIN
      DOUBLE PRECISION, DIMENSION(3) :: TST
C
C     Test function:
      DO 1001 II = 1,3
         TST(II) = II * 1.11D0 + IIN
 1001 CONTINUE
      RETURN
      END

This is compiled with gcc-fortran as follows:

gfortran -static -c -fdollar-ok -fno-align-commons TEST.for
gfortran -shared -mrtd -static -o TEST.dll TEST.def TEST.o

Where TEST.def maps TST to tst_

No problem thus far, however in python the issue arises "how do I call this function and handle the return value?"

Using the 'depwalker'-tool; the TST function apparently expects 2 arguments (tst_@8). Besides an integer, I assume this should be either a pointer to the output array or its length.

My python code is as follows:

import ctypes as cs
import numpy as np

#import dll library hooks:
tdll = cs.WinDLL(pathToDLL)
#test:
tdll.TST.restype = None
tdll.TST.argtypes = [cs.POINTER(cs.c_long), cs.POINTER(cs.c_double*3)]

#start testing:
Ar = [0.0, 0.0, 0.0]
_A = np.array(Ar).ctypes.data_as(cs.POINTER(cs.c_double*len(Ar)))
_L = cs.c_long(3)
tdll.TST(cs.byref(_L), _A)

The problem is that this code (together with any variants to this I try) will produce an error: OSError: exception: access violation writing 0x0000000F. If I try to pass the first argument ByValue, it will result in OSError: exception: access violation reading 0x0000000F

Can someone point me in the right direction here?

python
dll
fortran
ctypes
fortran77
asked on Stack Overflow Dec 26, 2014 by Unji • edited Dec 26, 2014 by Unji

1 Answer

0

After some tooling around; also thanks to the valuable suggestions by Vladimir F, a solution to the issue as described above has been found.

Some slight changes on the python side of things were required in order to make it work:

import ctypes as cs
import numpy as np

#import dll library handle:
tdll = cs.WinDLL(pathToDLL)
#specify result and argument types
tdll.TST.restype = None
tdll.TST.argtypes = [cs.POINTER(cs.POINTER(cs.c_double*3)), cs.POINTER(cs.c_long)]

#call the dll function 'TST':
Ar = (cs.c_double*3)()
_A = cs.pointer(Ar)
tdll.TST(cs.byref(_A), cs.byref(cs.c_long(3)))
result = Ar[:]

Hopefully this post might be of any help to someone else.

answered on Stack Overflow Dec 26, 2014 by Unji • edited May 23, 2017 by Community

User contributions licensed under CC BY-SA 3.0