Return an array of doubles via FORTRAN (DLL) for further processing in python


Yunzhi

I've been struggling with this issue for a while now, and searching for the query/applicable documentation hasn't yielded any workable results either. Hence posting here.

What do I want to accomplish:

  • I have some program written in FORTRAN77 that takes some parameters and returns a fixed length array of doubles.
  • I wish to use another programming language to call this function (currently, I use python for testing; but this will change at any time - so f2py is not an option here)

A FORTRAN routine can be summarized 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

Compile 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 so far, but the "how do I call this function and handle the return value?" question arises in python.

Using the "depwalker" tool; the TST function apparently expects 2 arguments ( tst_@8 ). In addition to integers, I think this should be 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 (and all the variations I've tried) will produce the error: OSError: exception: access violation writing 0x0000000F. If I try to pass the first parameter ByValue it results inOSError: exception: access violation reading 0x0000000F

Can someone point me in the right direction here?

Yunzhi

After some tools; also thanks to Vladimir F for his valuable advice, a solution to the above problem has been found.

In order to make it work, some minor changes are required on the python side:

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[:]

Hope this article is helpful to others.

Related


Python ctypes parameter with DLL - pointer to array of doubles

lightning I'm a novice programmer using ctypes with Python and trying to use functions from a DLL written in C. I've found a lot of similar questions on SO to solve, but none of the answers to this kind of conundrum. I have the DLL loaded just fine, but one of

Python ctypes parameter with DLL - pointer to array of doubles

lightning I'm a novice programmer using ctypes with Python and trying to use functions from a DLL written in C. I've found a lot of similar questions on SO to solve, but none of the answers to this kind of conundrum. I have the DLL loaded just fine, but one of

Python ctypes parameter with DLL - pointer to array of doubles

lightning I'm a novice programmer using ctypes with Python and trying to use functions from a DLL written in C. I've found a lot of similar questions on SO to solve, but none of the answers to this kind of conundrum. I have the DLL loaded just fine, but one of

Return values and data in a JSON array via Python

User 3458035 I have a JSON file named "Dev-Env-VNET-vnet-details.json"with the following details, { "location": "southeastasia", "name": "Dev-Env-VNET", "properties": { "addressSpace": { "addressPrefixes":

How to return a typed array in Fortran?

Eddie E Massey III I created a type called waveform in fortran and created a function that reads a file and creates an array of waveform types. I want the function to return an array of waveforms, but can't seem to figure out how to return the final array. Bel

How to return a typed array in Fortran?

Eddie E Massey III I created a type called waveform in fortran and created a function that reads a file and creates an array of waveform types. I want the function to return an array of waveforms, but can't seem to figure out how to return the final array. Bel

python callbacks in Fortran via ctypes

King Consider this C-interoperable Fortran subroutine called from Python with a Python callback function as an input parameter, and then calling it, module FortranFunc_mod ! C-interoperable interface for the python callback abstract interface

python callbacks in Fortran via ctypes

king Consider this C-interoperable Fortran subroutine called from Python with a Python callback function as an input parameter, and then calling it, module FortranFunc_mod ! C-interoperable interface for the python callback abstract interface

Pass array of doubles by reference from C to Delphi DLL

Level 0 For our Delphi (XE5) application we are developing an API. In order to pass data from Delphi DLL functions to and from the main program (C based; (console) C or C++ code applications or Matlab and Simulink), the array needs to be filled with doubles al

Pass array of doubles by reference from C to Delphi DLL

Level 0 For our Delphi (XE5) application we are developing an API. In order to pass data from Delphi DLL functions to and from the main program (C based; (console) C or C++ code applications or Matlab and Simulink), the array needs to be filled with doubles al

FORTRAN: access array via pointer matrix, performance

FortCpp I'm having trouble using pointers. Before I do this, I need to focus on performance. Suppose there is a 2D matrix like this: 0.0 0.0 0.0..... 0.0 0.7 0.5..... 0.0 0.5 0.8..... 0.0 0.3 0.8..... ..... I need to calculate the gradient of this thi

Return an array of strings of different lengths in Fortran

Keagansed I want to create a type in Fortran that contains an array of strings without explicitly assigning a length so I can return it from a function. Here are my types: type returnArr Character (*), dimension(4) :: array end type returnArr Here is the

Return an array of strings of different lengths in Fortran

Keagansed I want to create a type in Fortran that contains an array of strings without explicitly assigning a length so I can return it from a function. Here are my types: type returnArr Character (*), dimension(4) :: array end type returnArr Here is the

Return an array of strings of different lengths in Fortran

Keagansed I want to create a type in Fortran that contains an array of strings without explicitly assigning a length so I can return it from a function. Here are my types: type returnArr Character (*), dimension(4) :: array end type returnArr Here is the

How to convert an array of doubles in C to a list in python?

Carl Donitz my C code: #include <stdio.h> #include <stdlib.h> #include <math.h> double * Make_A(){ double A[2]; A[0]=0.00001; double *p=(double *)&A; return p; } And my python code: from ctypes import * lib_cpp = cdll.LoadLibrary('./test.so

Return value using int*(array) in python via cffi?

Observer I have a C function int * myfunc() { int * ret = (int *) malloc(sizeof(int)*5); ... return ret; } In python I can call it ret = lib.myfunc() But I can't seem to figure out how to actually use ret in the python code (ie convert it to an int