使用ctypes将字符串传递给Fortran子例程

时间:2017-12-05 22:45:24

标签: python fortran ctypes

我目前正在尝试将字符串传递给Fortran库。我已经从这个库中获得了其他函数,但是这个特殊的函数似乎是唯一的,因为它希望将一个字符串传递给它作为函数的参数。

查看源代码,该函数需要三个参数

SUBROUTINE EZVOLLIB(VOLEQI,DBHOB,HTTOT,VOL)

并且定义了参数:

  IMPLICIT NONE

  CHARACTER*(*)   VOLEQI
  CHARACTER*10 VOLEQ
  REAL DBHOB,HTTOT,TOPD, VOL(15), MHT
  INTEGER REGN,ERRFLG

在Python中,我对函数的调用看起来像

from ctypes import *

mylib = cdll.LoadLibrary('/home/bryce/Programming/opencompile/libvollib.so')

dbhob = c_float(42.2)
vol = (c_float * 15)()
voleqi = c_char_p("101DVEW119 ")

mylib.ezvollib_(voleqi, dbhob, vol)

这样运行没有分段错误,但似乎没有#34;填充"变量vol,带有所需的15个浮点值。

有没有办法让vol检索从EZVOLLIB函数返回的值?

1 个答案:

答案 0 :(得分:0)

这里有许多类似的问题,但很难找到完全重复。有几种可能的方法可以实现不同程度的通用正确性和可移植性。

最正确的方法是使用现代Fortran到C的互操作性,如fortran77, iso_c_binding and c string中所述,这需要编写更多的Fortran包装代码。

有些人严格禁止写Fortran,尽管这是唯一的便携式解决方案。在这种情况下,他们必须探索编译器中Fortran字符串的实际调用约定。通常,带有字符串长度的隐藏整数参数将传递给子例程。对于gfortran,请参阅https://gcc.gnu.org/onlinedocs/gfortran/Argument-passing-conventions.html

您的ctypes接口可以使用这些特定于编译器的调用约定,但接口将是编译器特定的。但是您已经依赖于特定名称mangling ezvollib_,这也是特定于编译器的。你可以在这里找到关于人们因依赖它而被咬伤的例子。

另请注意,正如High Performance Mark所指出的那样,所讨论的子程序有四个参数,而不是三个:EZVOLLIB(VOLEQI,DBHOB,HTTOT,VOL)。如mylib.ezvollib_(voleqi, dbhob, vol)中那样仅使用三个调用它是一个错误。您缺少HTTOT参数。