我有一个调用 Fortran 子例程的 Python 驱动程序。该子例程有 1 个字符,然后是 3 个整数。在我在开始处添加字符变量并且没有 argtypes 调用之前,它运行良好。但是在开始时添加字符(及其长度)加上 artgtypes 调用会出现 TypeError:
import ctypes as ct
lib = ct.CDLL('FTN_lib.dll')
fs = getattr(lib,'PY_OBJFUN_MOD_mp_GETSIZE')
fs.restype = None
fs.argtypes = [ct.c_char_p,ct.c_int,ct.c_int,ct.c_int,ct.c_int]
x = b'x ' + sys.argv[1].encode('UTF-8') + b' debug=900'
n = ct.c_int(0)
nl = ct.c_int(0)
nnl = ct.c_int(0)
fs(x, len(x), ct.byref(n), ct.byref(nl), ct.byref(nnl))
fs(x, len(x), ct.byref(n), ct.byref(nl), ct.byref(nnl))
ctypes.ArgumentError:参数 3:
:类型错误
看来添加 fs.argtypes 导致了问题。测试代码没有这个,而且运行得很好。添加 fs.argtypes 也会导致测试代码失败。因此,使用 ct.c_int 构造在调用中用作 ct_byref 会出现一些问题。
Fortran 代码头是:
subroutine getsize(file,n,nl,nnl)
implicit none
character(*), intent(in ) :: file
integer , intent(out) :: n
integer , intent(out) :: nl
integer , intent(out) :: nnl
Fortran 通过引用而不是值传递整数。
argtypes
对于整数参数应该是 ct.POINTER(ct.c_int)
。
注意:另一个答案的注释表示字符串大小在 32 位系统上应为 int32,在 64 位系统上应为 int64。我会用
c_size_t
。它还表示字符串长度被添加到参数列表的末尾而不是交错。我没有 Fortran 来测试。
尝试:
fs.argtypes = ct.c_char_p, ct.POINTER(ct.c_int), ct.POINTER(ct.c_int), ct.POINTER(ct.c_int), ct.c_size_t
x = b'x ' + sys.argv[1].encode('UTF-8') + b' debug=900'
n = ct.c_int(0)
nl = ct.c_int(0)
nnl = ct.c_int(0)
fs(x, ct.byref(n), ct.byref(nl), ct.byref(nnl), len(x))