F2py ошибка преобразования символа (*) в сегментации

Я пытаюсь использовать числовую модель Fortran90 с Python 3.5, используя f2py.

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. Есть ли способ заставить его работать без изменения кода на Фортране (модель длинная и сложная и, по возможности, я не хочу над ней работать)?

Массивы символов используются для определения строк в коде (например, сообщений об ошибках) и для обработки ввода / вывода из файлов. Одним из способов решения проблемы (если нет ответа на вопрос 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

Это операция, которую модель должна обработать, поскольку "chara" может быть путем к данным, и ее нужно инициализировать во время выполнения.

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

2 ответа

Решение

Отвечая на вопрос 2:

Строки в фортране обрабатываются как массив символов в f2py. Так что в вашем случае mod.modul.chara это массив 100 символы (в зависимости от длины, указанной в фортране). Накормить что-то вроде 'hello' в ручку вы можете сделать следующее:

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

Это должно позволить вам передать строку.

Вы, кажется, путаете строки переменной длины (что бы это ни было, что-то подобное в 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. Просто введите длину вручную, как в последнем примере выше. Нет никакой разницы, код euivalent.


На ваш номер (2). Это НЕ массив (в Фортране). Правила для массивов здесь не применяются. Но что более важно, это константа, вы ничего не можете ей присвоить, поэтому я не совсем понимаю, что вы имеете в виду. Если у вас есть символьная переменная, вы можете без проблем назначить более короткую строку:

character(10) :: ch = "abcd"
Другие вопросы по тегам