Проблема здесь определенно заключается в том, как F2PY оборачивает функции Фортрана, а не сам код Фортрана.
Чтобы немного лучше понять, как F2PY оборачивает функцию (особенно, если что-то не работает какожидается), это всегда помогает разделить процесс на части (см. Умный способ ).Поэтому сначала создайте файл подписи , позволяющий вам увидеть, как F2PY интерпретирует ваш код.Для вашего конкретного примера запустите:
f2py -m fortran_mods -h my_mod.pyf my_mod.F90
Это создаст файл сигнатуры my_mod.pyf
, который будет выглядеть примерно так:
python module fortran_mods ! in
interface ! in :fortran_mods
module my_mod ! in :fortran_mods:my_mod.F90
function my_func_without_r() result (myresult) ! in :fortran_mods:my_mod.F90:my_mod
integer :: myresult
end function my_func_without_r
function my_func_with_r() result (rresult) ! in :fortran_mods:my_mod.F90:my_mod
real :: rresult
end function my_func_with_r
end module my_mod
end interface
end python module fortran_mods
Очевидно, что F2PY неверно идентифицировал переменную результата my_func_with_r
rresult
как real
.Вы можете просто заменить real :: rresult
на integer :: rresult
в my_mod.pyf
, сделать следующий / второй шаг переноса F2PY и скомпилировать, используя исправленный файл подписи:
f2py -c my_mod.pyf my_mod.F90
Ваш скрипт на Python долженТеперь дайте ожидаемый результат.
Такой подход к изменению файла подписи может быть нежелателен, если у вас есть много функций для переноса.Что может вызывать трудности для F2PY, так это то, что в определениях вашей функции используются переменные результата, а определения типов для них не отображаются в теле функции (т. Е. Проблема F2PY, а не проблема Фортрана).Если вы измените определения функций, например, на:
function my_func_with_r() result(rresult)
integer :: rresult
rresult = 1
end function
или
integer function my_func_with_r()
my_func_with_r = 1
end function
, вы можете сделать F2PY-упаковку за один шаг, как вы делали изначально, и все равно должны получить правильный вывод.
Наконец, я добавлю еще один голос к проблемам, поднятым в комментариях: использование -fdefault-real-8
, когда обертывание функций с F2PY вызывает проблемы.Чтобы сделать процедуру Fortran вызываемой из Python , F2PY создает:
модуль расширения Python C / API (называемый модулем оболочки), который реализует функцию расширения Python (написанную на Cвызывается как функция-обертка), которая, в свою очередь, вызывает данную процедуру на Фортране.
Весь этот процесс основан на том, как F2PY интерпретирует типы данных из вашего исходного кода на Фортране - если исходный код скомпилирован с флагами компилятора, которыеИзмените объявленные типы данных, все обязательно закончится сбоем (прямо как real
/ integer
несоответствие вашего первоначального вопроса).Поэтому типы данных для ваших переменных и функций должны быть явно установлены в самом коде Фортрана, см. здесь и здесь о параметре kind
Фортрана в целом и здесь относится, в частности, к F2PY.