gpt4 book ai didi

python - 使用 ctypes 在 Python 中调用 Fortran 共享库

转载 作者:太空宇宙 更新时间:2023-11-04 03:17:54 24 4
gpt4 key购买 nike

我正在尝试在 Python 中使用 Fortran 模块。我在 Python 中有几个数组——包括数字和字符串。我在 Fortran 和 Python 中定义了数组,但我认为我对数值数组使用了错误的类型。我收到转换第一个参数(数字数组)失败的错误。我应该使用什么类型?

错误:

Traceback (most recent call last):
File "py_try.py", line 66, in <module>
writelittler.write_obs(p,z,t,td,spd,wdir,slp,ter,xlat,xlon,date_char,num_met,num_lev,kx,dd_strvar,station_strvar,synop,string4, bogus, iseq_num, iunit)
ctypes.ArgumentError: argument 1: <type 'exceptions.TypeError'>: Don't know how to convert parameter 1

语言:

subroutine write_obs(p, z, t, td, spd, wdir, xlon, kx, slp, ter, xlat,  date_char, dd, station, num_met, num_lev, synop, string4, bogus, iseq_num, iunit) bind(C, name='write_obs')
use iso_c_binding
implicit none
integer(c_int) k, kx, num_met, num_lev, iseq_num, iunit, ierr
real(kind=c_float) p(kx), slp(kx), z(kx), t(kx), td(kx)
real(kind=c_float) spd(kx), ter(kx), xlat(kx), xlon(kx), wdir(kx)
character(len=1,kind=c_char) date_char
character(len=1,kind=c_char) synop, string4
character(len=1,kind=c_char), intent(in) :: dd(kx)
character(len=1,kind=c_char), intent(in) :: station(kx)
logical(c_bool) bogus
character(len=84,kind=c_char) rpt_format
character(len=22,kind=c_char) meas_format
character(len=14,kind=c_char) end_format

rpt_format = ' ( 2f20.5 , 2a40 , '&
&' 2a40 , 1f20.5 , 5i10 , 3L10 , '&
&' 2i10 , a20 , 13( f13.5 , i7 ) )'

meas_format = ' ( 10( f13.5 , i7 ) ) '
end_format = ' ( 3 ( i7 ) )'

do 100 k=1 , kx

write ( UNIT = iunit , iostat = ierr , FMT = rpt_format ) &
& xlat(k), xlon(k), dd(k), station(k), &
& synop , string4, ter(k), num_met, 0, 0, iseq_num, 0, &
& .true., bogus, .false., &
& -888888, -888888, date_char, slp(k), 0, &
& -888888., 0, -888888., 0, -888888., 0, &
& -888888., 0, -888888., 0, -888888., 0, -888888., 0, &
& -888888., 0, -888888., 0, -888888., 0, -888888., 0, &
& -888888., 0

write ( UNIT = iunit , iostat = ierr , FMT = meas_format ) &
& p(k), 0, z(k), 0, t(k), 0, td(k), 0, &
& spd(k), 0, wdir(k), 0, &
& -888888., 0, -888888., 0, -888888., 0, -888888., 0


write ( UNIT = iunit , iostat = ierr, FMT = meas_format ) &
& -777777., 0, -777777., 0, float(num_lev), 0, &
& -888888., 0, -888888., 0, -888888., 0, &
& -888888., 0, -888888., 0, -888888., 0, &
& -888888., 0

write ( UNIT = iunit, iostat = ierr, FMT = end_format ) &
& num_lev, 0, 0

if (ierr .NE. 0 ) then
print '(A,I5,A)','Troubles writing a sounding.Error #', ierr
stop 'writing_error'
endif
100 continue
return
end subroutine write_obs

python :

import numpy as np
import ctypes
from ctypes import c_int, c_char
writelittler=ctypes.CDLL("/writelittler.so")
p = np.asarray([ 982.6, 999.7 ], dtype="float64")
p_strvar=ctypes.c_void_p(p.ctypes.data)

# [other numerical arrays omitted]

bogus = 0
kx=2
iseq_num = 0
iunit=2
date_char = ' 20160128060000'
dt=np.dtype('a40')
dd = np.asarray([ '1111111111111111111111111111111111111111', '6666666666666666666666666666666666666666', '9999999999999999999999999999999999999999' ], dtype=dt)
station = np.asarray([ 'V111111111111111111111111111111111111111','M111111111111111111111111111111111111111' ], dtype=dt)

dd_strvar=ctypes.c_void_p(dd.ctypes.data)
station_strvar=ctypes.c_void_p(station.ctypes.data)
num_met=6
num_lev=1
synop='FM-12 SYNOP '
string4=' '

writelittler.write_obs(p,z,t,td,spd,wdir,slp,ter,xlat, xlon,date_char,num_met,num_lev,kx,dd_strvar, station_strvar,synop,string4, bogus, iseq_num, iunit)

最佳答案

您没有在 Python 中指定 Fortran 子例程的参数类型。此外,您也不声明/初始化传递给 Fortran 的变量。因此,Python 不知道如何处理它。这就是它在错误消息中告诉您的内容。

由于 Fortran 默认使用引用调用,argtypes 是:

writelittler.write_obs.argtypes = [ POINTER(c_float), # p
POINTER(c_float), # z
POINTER(c_float), # t
POINTER(c_float), # td
POINTER(c_float), # spd
POINTER(c_float), # wdir
POINTER(c_int), # kx
POINTER(c_float), # slp
POINTER(c_float), # ter
POINTER(c_float), # xlat
POINTER(c_char), # date_char
POINTER(c_char), # dd
POINTER(c_char), # station
POINTER(c_int), # num_met
POINTER(c_int), # num_lev
POINTER(c_char), # synop
POINTER(c_int), # string4
POINTER(c_bool), # bogus
POINTER(c_bool), # string4
POINTER(c_int), # iseq_num
POINTER(c_int) # iunit
]

[这或许可以简化...]

此外,Fortran 子例程没有返回值:

writelittler.write_obs.restype = None

此外,您需要调整函数调用本身(在 Python 中):

writelittler.write_obs( p.ctypes.data_as(POINTER(c_float)), # Numpy data type
ctypes.byref(z), # ctypes data type
ctypes.byref(t),
ctypes.byref(td),
ctypes.byref(spd),
ctypes.byref(wdir),
ctypes.byref(slp),
ctypes.byref(ter),
ctypes.byref(xlat),
ctypes.byref(xlon),
ctypes.byref(date_char),
ctypes.byref(num_met),
ctypes.byref(num_lev),
ctypes.byref(kx),
ctypes.byref(dd_strvar),
ctypes.byref(station_strvar),
ctypes.byref(synop),
ctypes.byref(string4),
ctypes.byref(bogus),
ctypes.byref(iseq_num),
ctypes.byref(iunit) )

[这未经验证...]

既然 Python 知道会发生什么,您仍然需要声明缺少的变量。正如您的代码所知,它将导致错误:

Traceback (most recent call last):
File "test.py", line 51, in <module>
writelittler.write_obs(p,z,t,td,spd,wdir,slp,ter,xlat,
xlon,date_char,num_met,num_lev,kx,dd_strvar,
station_strvar,synop,string4, bogus, iseq_num, iunit)
NameError: name 'z' is not defined

关于python - 使用 ctypes 在 Python 中调用 Fortran 共享库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35652437/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com