I am trying to wrap some fortran code into python using the ctypes library but have am having major issues with the data transfer. When I print the data from my python script, it looks substantially different from when I print it within the fortran code. Can someone please help me figure out what is going on here? I tried playing around with the datatypes which did not fix the solution and so far I have not found any other SO questions that have addressed my issue. Also please note that using f2py will not work for the end product that this example refers too.
Below is an example of my code:
temp.f90
subroutine test(num_mod_sel,goodval,x,y,coeff,coeff_flag)
implicit none
! Input/Output
integer num_mod_sel, goodval
real, dimension(goodval,num_mod_sel) :: x
real, dimension(goodval) :: y
real, dimension(num_mod_sel) :: coeff
integer, dimension(num_mod_sel) :: coeff_flag
print*, num_mod_sel,goodval,x
return
end subroutine test
!===================================================================================================!
The above f90 code is compiled with:
gfortran -shared -fPIC -o temp.so temp.f90
test.py
from ctypes import CDLL,cdll, POINTER, c_int, c_float
import numpy as np
def test_fcode(num_mod_sel,goodval,x,y,coeff,coeff_flag):
fortran = CDLL('./temp.so')
fortran.test_.argtypes = [ POINTER(c_int),
POINTER(c_int),
POINTER(c_float),
POINTER(c_float),
POINTER(c_float),
POINTER(c_int) ]
fortran.test_.restype = None
num_mod_sel_ = c_int(num_mod_sel)
goodval_ = c_int(goodval)
x_ = x.ctypes.data_as(POINTER(c_float))
y_ = y.ctypes.data_as(POINTER(c_float))
coeff_ = coeff.ctypes.data_as(POINTER(c_float))
coeff_flag_ = coeff_flag.ctypes.data_as(POINTER(c_int))
fortran.test_(num_mod_sel_,goodval_,x_,y_,coeff_,coeff_flag_)
#Create some test data
num_mod_sel = 4
goodval = 10
x = np.full((num_mod_sel,goodval),999.,dtype=float)
x[:] = np.random.rand(num_mod_sel,goodval)
y = np.full(goodval,999.,dtype=float)
y[:] = np.random.rand(goodval)
coeff = np.empty(num_mod_sel,dtype=float)
coeff_flag = np.empty(num_mod_sel,dtype=int)
#Run the fortran code
test_fcode(num_mod_sel,goodval,x,y,coeff,coeff_flag)
print(x)
from the python code:
[[0.36677304 0.8734628 0.72076823 0.20234787 0.91754331 0.26591916 0.46325577 0.00334941 0.98890871 0.3284262 ] [0.15428096 0.24979671 0.97374747 0.83996786 0.59849493 0.55188578 0.9668523 0.98441142 0.50954678 0.22003844] [0.54362548 0.42636074 0.65118397 0.69455346 0.30531619 0.88668116 0.97278714 0.29046492 0.64851937 0.64885967] [0.31798739 0.37279389 0.88855305 0.38754276 0.94985151 0.56566525 0.99488508 0.13812829 0.0940132 0.07921261]]
print*, x
from f90:
-2.91465824E-17 1.68338645 13.0443134 1.84336567 -7.44153724E-34 1.80519199 -2.87629426E 27 1.57734776 -1297264.38 1.85438573 -236487.531 1.63295949 -1.66118658E-33 1.73162782 -6.73423983E-09 0.919681191 -1.09687280E 21 1.87222707 5.50313165E 09 1.66421306 8.38275158E 34 1.52928090 -2.15154066E-13 1.62479663 3.88800366E 30 1.86843681 127759.977 1.83499193 -3.55062879E 15 1.77462363 2.43241945E 19 1.76297140 3.16150975E-03 1.86671305 1.35183692E 21 1.87110281 1.74403865E-31 1.75238669 9.85857248E-02 1.59503841 -2.33541620E 30 1.79045486 -1.86185171E 11 1.78229403 4.23132255E-20 1.81525886 2.96771497E-04 1.82888138 -4.55096013E-26 1.86097753 0.00000000 3.68934881E 19 -7.37626273E 15 1.58494916E 29 0 -1064355840 -646470284 -536868869
CodePudding user response:
The problem is a mismatch of datatypes.
The Fortran real
is usually a 32 bit float (C float
) while numpy interprets the Python datatype float
as numpy.float_
which is an alias of numpy.float64
, the C double
with 64 bits.
Solution: In Python use numpy.float32
as dtype
for numpy array creation.