使用ctypes在Python中使用Fortran可选参数
作者:互联网
我应该如何使用CType正确处理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的文档中我相信我正确地传递了变量,但可能有一些我遗漏的微妙之处?当我尝试运行代码时,它会崩溃.
解决方法:
好的想出了一些事情.
>我需要使用不是argparse的argtypes
>可选参数只有在Fortran中定义为由VALUE传递时才需要隐藏的逻辑变量.如果它们没有被传递,那么仍然需要传递NULL指针.
>所有整数都需要通过引用传入.
所以Fortran代码仍然如上所述,但Python代码应该是这样的
import ctypes as ct
libtest = ct.cdll.LoadLibrary("libtest.so")
fstr_h = getattr(libtest,'__test_module_MOD_fstr_test')
fstr_h.argtypes = [ ct.POINTER(ct.c_int), \ #iunit
ct.POINTER(ct.c_int), \ #istat
ct.c_char_p, \ #file1
ct.c_char_p, \ #file2
ct.c_char_p, \ #file3
ct.POINTER(ct.c_int), \ #test
ct.c_char_p,\ #file4
ct.c_char_p, \ #file5
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)
file1 = "one"
file2 = "two"
file3 = "three"
file4 = "four"
file5 = "five"
fstr_h(ct.byref(iunit_temp),ct.byref(istat_temp), \
file1.encode('UTF-8'),file2.encode('UTF-8'),file3.encode('UTF-8'),\
ct.byref(record_in_temp),file4.encode('UTF-8'),file5.encode('UTF-8'), \
len(file1),len(file2),len(file3),len(file4),len(file5))
现在这是猜想,但我怀疑任何在Fortran中输入为INTNET(in)的变量都可以作为值而不是指针传递.但是,由于INTENT(inout)和INTENT(out)变量的值已更改,我认为需要通过指针传递. Fortran中经常输入的参数也可以这么说.
标签:python,fortran,ctypes,gfortran 来源: https://codeday.me/bug/20190701/1347613.html