【问题标题】:F2py converting character(*) segmentation faultF2py 转换字符(*)分段错误
【发布时间】:2017-04-06 08:40:39
【问题描述】:

我正在尝试使用 f2py 将 Fortran90 数值模型与 Python 3.5 一起使用。

f2py -c module.f90 -m mod --fcompiler=gfortran

该模型是一个包含变量、函数和子例程的 Fortran 模块。我在这里发布一个代码示例,它具有数值模型的所有功能

module modul

implicit none
integer :: inte
real :: re
integer, dimension(3) :: array
CHARACTER(*), PARAMETER :: chara = "helloWorld"

contains
    integer function fun()
        fun = array(1) + array(2) + array(3)
    end function

    subroutine subrout(a,b)
        real, intent(out) :: b
        integer, intent(out) :: a
        a = inte + fun()
        b = re
        write(*,*) chara
    end subroutine subrout

end module modul

使用 f2py 转换代码可以正常工作,但是当我在 Python 中导入模块时,我收到分段错误错误

>>> import mod
Segmentation fault (core dumped)

我意识到问题取决于字符数组的未指定维度

CHARACTER(*), PARAMETER :: chara = "helloWorld"

因为,如果我删除那行代码或为数组分配一个固定维度(如 CHARACTER(20) ),该模块在 Python 中可以正常工作。

1.有没有办法让它在不修改 Fortran 代码的情况下工作 (模型又长又复杂,如果可能的话,我不想 工作)?

字符数组用于定义代码中的字符串(如错误消息)并处理文件的输入/输出。解决问题的一种方法(如果问题 1 没有答案)可以为所有字符串定义一个固定的最大维度(即 INTEGER、PARAMETER :: lenChar = 100),然后使用

CHARACTER(lenChar), PARAMETER :: chara

而不是之前的声明。在这种情况下,模块在 Python 中成功导入,但是当我尝试修改数组内容时,它需要输入 lenChar long (同样的问题出现在其他类型的数组中,如 INTEGER 或 REAL 并且不依赖于 PARAMETER 属性)

mod.modul.chara = "hello"
0-th dimension must be fixed to 100 but got 5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
SystemError: error return without exception set

这是模型需要处理的操作,因为“字符”可能是数据的路径,需要在运行时初始化。

2。如果问题 (1) 没有答案并且我需要以这种方式继续,我如何为数组分配比数组长度短的输入?

System information:
OS: Ubuntu 16.04
Python 3.5.2
f2py Version:     2
numpy Version: 1.12.1
GNU Fortran (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609

【问题讨论】:

  • 对所有 Fortran 问题使用标签 fortran。您还使用 python 而不是 python-3.5。
  • 不是用 f2py3 调用 Python 3 吗?也许只在我的 Linux 发行版上......
  • 假定长度字符常量在 Fortran 90 中是合法的。F2py 应该能理解它们。
  • 实际上,MCVE 可以比您的示例短得多。三行就够了。 module modul; CHARACTER(*), PARAMETER :: chara = "helloWorld"; end module modul 看不到阵列。我没有得到你的分数 (2)。
  • @VladimirF: (1) 感谢您的更正 (2) 我尝试使用 f2py3 和 f2py3.5 并没有解决问题 (3) 我没有收到此评论 ( 4)如果我不能为字符分配可变长度,那么我必须在编译时确定足够长的固定长度以包含任何合理的字符串。这样,如果字符串比长度短,那么代码就可以工作,如果字符串更长,它就不起作用,因为没有剩下的内存了。正如您在第 6 段代码中看到的,Python 要求字符串与字符的长度一样长。有没有办法插入短字符串?

标签: python arrays fortran character f2py


【解决方案1】:

回答问题 2:

fortran 中的字符串在 f2py 中被视为字符数组。因此,在您的情况下,mod.modul.chara 是一个 100 字符数组(取决于 fortran 中指定的长度)。要将 'hello' 之类的内容输入到句柄中,您可以执行以下操作:

for i,j in enumerate('hello'):
    mod.modul.chara[i]=j

这应该可以让你传递字符串。

【讨论】:

  • 这行得通,谢谢。我想我会继续(2)的方式,除非有人建议完成(1)的事情
  • mod.modul.chara 是一个常量,这个命令应该会立即失败。
  • @VladimirF 这种方法适用于我,OP 声称它也适用于他。它可能有效,因为我们已经声明了字符串元素的长度,并且没有在 fortran 中为其分配任何值..?
  • 如果是parameter,肯定会crash。
【解决方案2】:

您似乎混淆了可变长度字符串(无论可能是什么,Fortran 2003 中的类似内容)、字符串常量和采用您传递的长度的虚拟参数。可能你想要:

subroutine sub(ch)
  character(*), intent(in) :: ch

  print *, ch
end

这与您的示例完全不同。这里的参数ch 将接受您在此处传递的任何长度的字符串。


问题在于假定的长度字符常量。这足以触发错误

module m
  CHARACTER(*), PARAMETER :: chara = "helloWorld"
end module m

这不是一个字符数组,它是一个假定长度的标量字符串。

完全等价于

module m
  CHARACTER(10), PARAMETER :: chara = "helloWorld"
end module m

唯一的区别是,如果您懒得手动计算长度(或者您不时更改它),编译器会在前一种情况下自动获取长度。

后一个版本在 f2py 中可以正常工作:

f2py -c -m f2pychar f2pychar.f90 

ipython

In [1]: import f2pychar 

In [2]: print f2pychar.modul.chara
['h' 'e' 'l' 'l' 'o' 'W' 'o' 'r' 'l' 'd']

F2py 应该理解它,但它似乎没有。这是 f2py 中的一个严重错误。只需手动输入长度,如上面的后一个示例所示。没有区别,代码是等效的。


到您的号码 (2)。它不是一个数组(在 Fortran 中)。数组的规则在这里不适用。但更重要的是,它是一个常数,你不能给它分配任何东西,所以我不太明白你的意思。如果你有一个字符变量,你可以毫无问题地分配一个较短的字符串:

character(10) :: ch = "abcd"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-23
    • 1970-01-01
    • 2012-11-14
    相关资源
    最近更新 更多