【发布时间】:2018-02-24 09:21:23
【问题描述】:
我应该如何使用 CTypes 在 Python 中正确处理可选的 Fortran 参数?例如,假设 Fortran 子例程类似于:
MODULE test_module
INCLUDES
SUBROUTINE fstr_test(iunit, istat, file1, file2, file3, test, file4, file5)
IMPLICIT NONE
INTEGER, INTENT(inout) :: iunit
INTEGER, INTENT(out) :: istat
CHARACTER(LEN=*), INTENT(in) :: file1, file2, file3
CHARACTER(LEN=*), INTENT(in), OPTIONAL :: file4, file5
INTEGER, OPTIONAL :: test
WRITE(6,*) file1, file2, file3
RETURN
END SUBROUTINE fstr_test
END MODULE test_module
现在python应该看起来像
import ctypes as ct
libtest = ct.cdll.LoadLibrary("libtest.so")
fstr_h = getattr(libtest,'__test_module_MOD_fstr_test')
fstr_h.argparse = [ ct.c_int, \ #iunit
ct.c_int, \ #istat
ct.c_char_p, \ #file1
ct.c_char_p, \ #file2
ct.c_char_p, \ #file3
ct.c_int, \ #test
ct.c_char_p,\ #file4
ct.c_char_p, \ #file5
ct.c_bool, ct.c_bool, ct.c_bool,\ # Three optional arguments
ct.c_long, ct.c_long, ct.c_long, ct.c_long, ct.c_long] # lengths
fstr_h.restype=None
iunit_temp = ct.c_int(0)
istat_temp = ct.c_int(0)
record_in_temp = ct.c_int(0)
opt1 = ct.c_bool(True)
opt2 = ct.c_bool(True)
opt3 = ct.c_bool(True)
file1 = "one"
file2 = "two"
file3 = "three"
file4 = "four"
file5 = "five"
fstr_h(iunit_temp,ct.byref(istat_temp), \
file1.encode('UTF-8'),file2.encode('UTF-8'),file3.encode('UTF-8'),\
record_in_temp,file4.encode('UTF-8'),file5.encode('UTF-8'), \
ct.byref(opt1), ct.byref(opt2), ct.byref(opt3),\
len(file1),len(file2),len(file3),len(file4),len(file5))
从 gcc 在其argument passing conventions 上的文档中,我相信我正确地传递了变量,但我可能遗漏了一个微妙之处?当我尝试运行代码时它崩溃了。
【问题讨论】:
-
您能否将您的(Python 端)参数与您理解的 gcc(通过参数传递约定)所期望的相匹配?这将帮助我(谁不做 python/ctypes)评估你的信念。
-
什么是
argparse?尝试设置argtypes属性。 -
如果通过引用传递,您希望 argtype 为
ct.POINTER(ct.c_int)以传递ct.byref(iunit_temp),例如。您也可以使用file1 = b'one'并显式跳过对文件进行编码。 -
我切换到
argtypes这并不能解决我的问题,但可能会修复我使用 argparse 的其他一些代码(请参阅此问题的解决方案 stackoverflow.com/questions/42328866/…)
标签: python fortran ctypes gfortran