Python Forum
Trying to debug segfault in ctypes binding to Fortran - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Trying to debug segfault in ctypes binding to Fortran (/thread-40639.html)



Trying to debug segfault in ctypes binding to Fortran - bthomas - Aug-30-2023

Hi,

I am just trying to learn creating Python bindings to legacy Fortran using the ctypes module. My code is segfaulting in the Fortran function invocation. I was not able to decipher what gdb was telling me. I would be grateful to be pointed in the right direction here.

A simple Fortran function I am trying to bind is given below. It was compiled using "gfortran -shared euler.f -o euler.so"

       subroutine euler(f, neq, y, t, tout, h)
       implicit none
       real y(neq), t, tout, h, dy(neq), ti
       integer neq, i, stepnum
       stepnum = 1
       ti = t
c      Euler iteration
 10    continue
          call f( neq, t, y, dy )
          do 20 i = 1, neq
             y(i) = y(i) + h*dy(i)
 20       continue
          t = ti + stepnum*h
          stepnum = stepnum + 1
       if ( t < tout ) goto 10
       return
       end
The Python code calling this Fortran subroutine is

import ctypes as ct

flib = ct.CDLL('euler.so')
ode_spec = ct.CFUNCTYPE(None, ct.c_int, ct.c_float, ct.POINTER(ct.c_float), ct.POINTER(ct.c_float))

flib.euler_.restype = None
flib.euler_.argtypes = [
    ct.POINTER(ode_spec),
    ct.c_int,
    ct.POINTER(ct.c_float),
    ct.c_float,
    ct.c_float,
    ct.c_float
]

@ode_spec
def df(neq, t, y, dy):
    dy[0] = y[0]
    return

t = 0.1
to = 0.2
neq = 1
realarr = ct.c_float * neq
y = realarr(0.1)
h = 0.001
flib.euler_(df, len(y), y, t, to, h)



RE: Trying to debug segfault in ctypes binding to Fortran - bthomas - Sep-01-2023

Finally got it working. The code below worked.

import ctypes as ct

flib = ct.CDLL('euler.so')
ode_spec = ct.CFUNCTYPE(None, ct.POINTER(ct.c_int), ct.POINTER(ct.c_float), ct.POINTER(ct.c_float * 1), ct.POINTER(ct.c_float * 1))

flib.euler_.restype = None
flib.euler_.argtypes = [
    ode_spec,
    ct.POINTER(ct.c_int),
    ct.POINTER(ct.c_float * 1),
    ct.POINTER(ct.c_float),
    ct.POINTER(ct.c_float),
    ct.POINTER(ct.c_float)
]

@ode_spec
def df(neq, t, y, dy):
    dy[0] = y[0]
    return

t = ct.c_float(0.1)
to = ct.c_float(0.2)
neq = ct.c_int(1)
relarr = ct.c_float * 1
y = relarr()
y[0] = 0.1
h = ct.c_float(0.001)
flib.euler_(df, ct.byref(neq) , ct.byref(y), ct.byref(t), ct.byref(to), ct.byref(h))