Calling function from Fortran DLL using a void callback function

52 views
Skip to first unread message

Nico

unread,
Oct 27, 2020, 9:51:36 AM10/27/20
to python-cffi

Hi everyone,
I'm trying to get a 3rd party 32bit Fortran DLL up and running. My problem is, that the kernel dies when I try to call the following function. I'm thinking, that the void callback function is causing the problem.
Documentation of the DLL/Function: https://www.nag.com/numeric/nl/nagdoc_26.2/nagdoc_fl26.2/html/d02/d02bhf.html
The documentation also offers an example written in fortran which I tried to implement in the code below.

Thanks for your help!

Regards,
Nico Korell


I'm using Spyder with Python 3.8.3 32bit on Win10 64bit (CFFI '1.14.2').

Code:
import numpy as np
import cffi as cf

"""void D02BHF(double *x,const double *xend, const long long *n, double y[],
          double *tol, const long long *irelab, const double *hmax,
          void fcn(const double *x, const double y[], double f[]),
          double g(const double *x, const double y[]),
          double w[], long long *ifail);"""

intT = "int*"
intTN = np.int32
decT = "double*"
decTN = np.float64

dTypesFcn =  [decT, decT, decT]
strFcn = "void fcn(" + ", ".join(dTypesFcn) + ")"
dTypesG =  [decT, decT]
strG = "double g(" + ", ".join(dTypesG) + ")"

dTypesMain = [decT, decT, intT, decT, decT, intT, decT, strFcn, strG, decT, intT]
strMain = "void D02BHF(" + ", ".join(dTypesMain) + ");"

ffi=cf.FFI()
lib=ffi.dlopen("C:\Windows\SysWOW64\DLL20DD")
ffi.cdef(strMain)

# Input
n = ffi.new(intT, 3)
irelab = ffi.new(intT, 0)
xend = ffi.new(decT, 10)
hmax = ffi.new(decT, 0.0)

# In/Out
x = ffi.new(decT, 0.0)
yx = np.array([0.5,  0.5,  np.pi/5], dtype=decTN, order='F')
y = ffi.cast(decT, yx.__array_interface__['data'][0])
tol = ffi.new(decT, 1e-4)
ifail = ffi.new(intT, 0)

# Output
wx = np.ones((n[0],7),dtype=decTN, order='F')
w = ffi.cast(decT, wx.__array_interface__['data'][0])

# Callback Functions
# @ffi.callback("void fcn(double *x, double y[], double f[])")
@ffi.callback(strFcn)
def fcn(x, y, f):
    # print(x[0],f[0])
    print(ifail[0])
    f[0] = np.tan(y[2])
    f[1] = -0.032*np.tan(y[2])/y[1]  - 0.02*y[1]/np.cos(y[2])
    f[2] = -0.032/y[2]**2

# @ffi.callback("double g(double *x, double y[])")
@ffi.callback(strG)
def g(x, y):
    return y[0]

lib.D02BHF(x, xend, n, y, tol, irelab, hmax, fcn, g, w, ifail)
print(x[0])

Armin Rigo

unread,
Oct 27, 2020, 1:22:48 PM10/27/20
to pytho...@googlegroups.com
Hi,

On Tue, 27 Oct 2020 at 14:51, Nico <Nico....@web.de> wrote:
> """void D02BHF(double *x,const double *xend, const long long *n, double y[],
> double *tol, const long long *irelab, const double *hmax,
> void fcn(const double *x, const double y[], double f[]),
> double g(const double *x, const double y[]),
> double w[], long long *ifail);"""
>
> intT = "int*"

Maybe you should use "long long" instead of "int"?

Armin

Nico

unread,
Oct 27, 2020, 1:34:57 PM10/27/20
to python-cffi
Hi Armin,

oh sorry, that was just the string from an early version. I already tested the datatypes, that was not it.

One strange thing that I figured out printing some information from inside the callback function was, that the function is being called like 23 times before crashing.
Another thing is, that I tested the ODE with Matlab and figured out, that the result given from the example in the documentation is wrong. Right answer should be about x=5.8
Reply all
Reply to author
Forward
0 new messages