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"