使用 Ctypes 将 Numpy 数组传输到 Fortran 时出现问题



我正在尝试使用 ctypes 库将一些 fortran 代码包装到 python 中,但在数据传输方面遇到了重大问题。当我从 python 脚本打印数据时,它看起来与我在 fortran 代码中打印数据时大不相同。有人可以帮我弄清楚这里发生了什么吗?我尝试使用无法解决解决方案的数据类型,到目前为止,我还没有找到任何其他解决我问题的 SO 问题。另请注意,使用 f2py 也不适用于此示例所指的最终产品。

下面是我的代码示例:

温度.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
!===================================================================================================!

上面的 f90 代码编译为:

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)

从python代码print(x)

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

来自 f90 的print*, x

-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

问题是数据类型不匹配。

Fortranreal通常是一个 32 位浮点数 (Cfloat),而 numpy 将 Python 数据类型float解释为numpy.float_,它是numpy.float64的别名,Cdouble有 64 位。

解决方案:在 Python 中使用numpy.float32作为创建 numpy 数组的dtype

最新更新