Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用ctypes调用Python中的Fortran共享库_Python_Fortran_Ctypes - Fatal编程技术网

用ctypes调用Python中的Fortran共享库

用ctypes调用Python中的Fortran共享库,python,fortran,ctypes,Python,Fortran,Ctypes,我试图在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

我试图在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
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
将numpy导入为np
导入ctypes
从ctypes导入c_int、c_char
writelittler=ctypes.CDLL(“/writelittler.so”)
p=np.asarray([982.6999.7],dtype=“float64”)
p\u strvar=ctypes.c\u void\u p(p.ctypes.data)
#[省略其他数字数组]
虚假=0
kx=2
iseq_num=0
iunit=2
日期字符='20160128060000'
dt=np.dtype('a40')
dd=np.asarray(['11111111111111111111111111111111111111111111111','66666666666666666666666666','99999999999999999999999',dtype=dt)
station=np.asarray(['V111111111111111111','M111111111111111111111',dtype=dt)
dd_strvar=ctypes.c_void_p(dd.ctypes.data)
station\u strvar=ctypes.c\u void\u p(station.ctypes.data)
num_met=6
num_lev=1
synop='FM-12 synop'
字符串4=''
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,false,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中):

[这未经验证…]

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

回溯(最近一次呼叫最后一次):
文件“test.py”,第51行,在
写入者。写入对象(p、z、t、td、spd、wdir、slp、ter、xlat、,
xlon,date\u char,num\u met,num\u lev,kx,dd\u strvar,
电台(标准电台、会议、string4、伪造、iseq_num、iunit)
NameError:未定义名称“z”

传递numpy数组时,请使用其
ctypes
属性,例如
x.ctypes
而不是
c\u void\p(x.ctypes.data)
。对于第一个参数,您错误地传递了numpy数组
p
,而不是
p.ctypes
。确保数字类型匹配(例如
c_float
float32
c_double
float64
)。对于按值传递,Fortran的c绑定不要求您显式声明参数为by
value
?否则,参数将通过引用传递。例如,
integer(c_int)、intent(in)、value::k、kx
@eryksun。但是我建议将argtypes显式声明为
指针(c_float)
,等等@Palina在Python代码中指定
z
t
,以及所有其他变量的位置?您正在用Fortran访问它们!如果我要声明
argtypes
,那么我会使用numpy指针类型,比如
npf8arr\u t=np.ctypeslib.ndpointer(dtype='float64')
。这样,OP可以直接传递numpy数组
x
,而不是传递
x.ctypes
。此外,如果OP控制Fortran API,则应将整数参数更改为通过
值传递。否则这将是一个乏味的接口,例如
num_met=ctypes.c_int(6)
<代码>写入对象(…,ctypes.byref(num_met),…)
。而不是简单地
num_met=6
write\u obs(…,num\u met,…)
@eryksun实际上,我更喜欢更乏味的写作方式。通常,会传递大的numpy数组,我会尽量避免复制内容。但是你是对的,我也应该将更改添加到函数调用中。谁说要复制数组参数?
ndpointer
类型不复制参数。它的
from_param
方法验证numpy数组类型是否与类型、维度、形状和标志中所需的约束匹配,然后它只传递
ctypes
属性,该属性将
\u定义为参数\u
属性,该属性将数组的基地址作为
c\u void\p
实例。没有创建副本。@eryksun在Fortran中,如果指定
value
则切换为按值调用。
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