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:
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
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?
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.
User contributions licensed under CC BY-SA 3.0