Файл подписи
Файл определения интерфейса (.pyf) — это способ точной настройки интерфейса между Python и Fortran. Спецификация синтаксиса файлов подписи (.pyf файлы) основана на спецификации языка Fortran 90/95. Почти все стандартные конструкции Fortran понимаются, как в свободном, так и в фиксированном формате (напоминаем, что Fortran 77 является подмножеством Fortran 90/95). F2PY вводит некоторые расширения спецификации языка Fortran 90/95, которые помогают в разработке интерфейса Fortran к Python, делая его более «pythonic».
Файлы подписи могут содержать произвольный код Fortran, поэтому любой код Fortran 90/95 может рассматриваться как файл подписи. F2PY игнорирует конструкции Fortran, не имеющие значения для создания интерфейса. Однако это также означает, что ошибки синтаксиса не обнаруживаются F2PY и будут обнаружены только при построении библиотеки.
Примечание
В настоящее время F2PY может давать сбой с некоторыми допустимыми конструкциями Fortran. В случае возникновения подобных проблем, вы можете проверить отслеживание проблем на GitHub NumPy в поисках возможных решений или идей в разработке.
В целом, содержимое файлов подписи чувствительно к регистру. При сканировании кода Fortran для генерации файла подписи F2PY автоматически преобразует все буквы в нижний регистр, за исключением многострочных блоков или в случае использования опции --no-lower.
Синтаксис файлов подписи представлен ниже.
Синтаксис файлов подписи
Блок модуля Python
Файл подписи может содержать один (рекомендуемый) или более python
module блоков. Блок python module описывает содержимое модуля расширения Python/C <modulename>module.c, который генерирует F2PY.
Предупреждение
Исключение: если <modulename> содержит подстроку __user__, то соответствующий python module блок описывает подписи функций обратного вызова (см. Аргументы обратного вызова).
Блок python module имеет следующий структуру:
python module <modulename>
[<usercode statement>]...
[
interface
<usercode statement>
<Fortran block data signatures>
<Fortran/C routine signatures>
end [interface]
]...
[
interface
module <F90 modulename>
[<F90 module data type declarations>]
[<F90 module routine signatures>]
end [module [<F90 modulename>]]
end [interface]
]...
end [python module [<modulename>]]
Здесь квадратные скобки [] обозначают необязательную секцию, точки ... указывают одну или несколько предыдущих секций. Таким образом, []... следует понимать как ноль или более предыдущих секций.
Подписи процедур Fortran/C
Подпись процедуры Fortran имеет следующую структуру:
[<typespec>] function | subroutine <routine name> \
[ ( [<arguments>] ) ] [ result ( <entityname> ) ]
[<argument/variable type declarations>]
[<argument/variable attribute statements>]
[<use statements>]
[<common block statements>]
[<other statements>]
end [ function | subroutine [<routine name>] ]
Из подписи процедуры Fortran F2PY генерирует функцию расширения Python/C, которая имеет следующую подпись:
def <routine name>(<required arguments>[,<optional arguments>]):
...
return <return variables>
Подпись блока данных Fortran имеет следующую структуру:
block data [ <block data name> ] [<variable type declarations>] [<variable attribute statements>] [<use statements>] [<common block statements>] [<include statements>] end [ block data [<block data name>] ]
Объявления типов
Определение части <argument/variable type declaration>:
<typespec> [ [<attrspec>] :: ] <entitydecl>
где
<typespec> := byte | character [<charselector>]
| complex [<kindselector>] | real [<kindselector>]
| double complex | double precision
| integer [<kindselector>] | logical [<kindselector>]
<charselector> := * <charlen>
| ( [len=] <len> [ , [kind=] <kind>] )
| ( kind= <kind> [ , len= <len> ] )
<kindselector> := * <intlen> | ( [kind=] <kind> )
<entitydecl> := <name> [ [ * <charlen> ] [ ( <arrayspec> ) ]
| [ ( <arrayspec> ) ] * <charlen> ]
| [ / <init_expr> / | = <init_expr> ] \
[ , <entitydecl> ]
и
-
<attrspec>— это список атрибутов, разделённых запятыми; -
<arrayspec>— это список границ размерностей, разделённых запятыми; -
<init_expr>— это C-выражение; -
<intlen>может быть отрицательным целым числом дляintegerспецификаций типов. В таких случаяхinteger*<negintlen>представляет собой беззнаковые целые числа C;
Если у аргумента нет <argument type declaration>, его тип определяется по применению правил implicit к его имени.
Операторы
Операторы атрибутов
<argument/variable attribute statement> подобен <argument/variable type declaration>, но без <typespec>.
Оператор атрибута не может содержать другие атрибуты, и <entitydecl> может быть только списком имён. См. Атрибуты для получения дополнительной информации об атрибутах, которые могут использоваться F2PY.
Операторы USE
-
Определение части
<use statement>:use <modulename> [ , <rename_list> | , ONLY : <only_list> ]
где
<rename_list> := <local_name> => <use_name> [ , <rename_list> ]
- В настоящее время F2PY использует операторы
useтолько для связи модулей обратного вызова иexternalаргументов (функций обратного вызова). См. Аргументы обратного вызова.
Операторы COMMON блока
-
Определение части
<common block statement>:common / <common name> / <shortentitydecl>
где
<shortentitydecl> := <name> [ ( <arrayspec> ) ] [ , <shortentitydecl> ]
- Если блок
python moduleсодержит два или более блокаcommonс одинаковым именем, переменные из дополнительных объявлений добавляются. Типы переменных в<shortentitydecl>определяются с помощью<argument type declarations>. Обратите внимание, что соответствующий<argument type declarations>может содержать спецификации массивов; в таком случае их не нужно указывать в<shortentitydecl>.
Другие операторы
-
Часть
<other statement>относится к другим конструкциям языка Fortran, которые не описаны выше. F2PY игнорирует большинство из них, за исключением следующих:-
callоператоры и вызовы функцийexternalаргументов (см. подробнее об внешних аргументах); -
-
includeоператоры -
include '<filename>' include "<filename>"
Если файл
<filename>не существует, операторincludeигнорируется. В противном случае файл<filename>включается в файл подписи.includeоператоры могут использоваться в любой части файла подписи, также вне блоков подписи процедур Fortran/C.
-
-
-
implicitоператоры -
implicit none implicit <list of implicit maps>
где
<implicit map> := <typespec> ( <list of letters or range of letters> )
Для определения спецификации типа переменной (из первой буквы её имени) используются неявные правила, если переменная не определена с помощью
<variable type declaration>. Правила неявной типизации по умолчанию задаются:implicit real (a-h,o-z,$_), integer (i-m)
-
-
-
entryоператоры -
entry <entry name> [([<arguments>])]
F2PY генерирует обёртки для всех имён входа, используя подпись блока процедуры.
Примечание
Оператор
entryможет использоваться для описания подписи произвольной подпрограммы или функции, позволяя F2PY генерировать несколько обёрток из подписи одного блока процедуры. Существуют некоторые ограничения при выполнении этого действия:fortrannameиспользовать нельзя,callstatementиcallprotoargumentможно использовать только если они применимы ко всем процедурам входа и т. д.
-
-
Операторы F2PY
Кроме того, F2PY вводит следующие операторы:
threadsafe-
Использует блок
Py_BEGIN_ALLOW_THREADS .. Py_END_ALLOW_THREADSвокруг вызова функции Fortran/C. callstatement <C-expr|multi-line block>-
Заменяет сгенерированный F2PY оператор вызова функции Fortran/C на
<C-expr|multi-line block>. Обёрнутая функция Fortran/C доступна как(*f2py_func).Для поднятия исключения установите
f2py_success = 0в<C-expr|multi-line block>. callprotoargument <C-typespecs>-
Когда используется оператор
callstatement, F2PY может не сгенерировать правильные прототипы для функций Fortran/C (потому что<C-expr>может содержать вызовы функций, а F2PY не может определить, какой должен быть правильный прототип).С помощью этого оператора вы можете явно указать аргументы соответствующего прототипа:
extern <return type> FUNC_F(<routine name>,<ROUTINE NAME>)(<callprotoargument>);
fortranname [<actual Fortran/C routine name>]-
F2PY позволяет использовать произвольный
<routine name>для заданной функции Fortran/C. Затем этот оператор используется для<actual Fortran/C routine name>.Если оператор
fortrannameиспользуется без<actual Fortran/C routine name>, генерируется обёртка-заглушка. usercode <multi-line block>-
При использовании внутри блока
python module, данный C-код будет вставлен в сгенерированный исходный код C/API непосредственно перед определениями функций-обёртки.Здесь вы можете определить произвольные C-функции для использования при инициализации необязательных аргументов.
Например, если оператор
usercodeиспользуется дважды внутри блокаpython module, то второй многострочный блок вставляется после определения внешних процедур.При использовании внутри
<routine signature>, данный C-код будет вставлен в соответствующую функцию-обёртку сразу после объявления переменных, но до любых C-операторов. Таким образом, последующиеusercodeмогут содержать как объявления, так и C-операторы.При использовании внутри первого блока
interface, данный C-код будет вставлен в конце функции инициализации модуля расширения. Это позволяет модифицировать словарь модулей расширения и имеет множество применений; например, для определения дополнительных переменных. pymethoddef <multiline block>-
Это многострочный блок, который будет вставлен в определение массива методов модуля
PyMethodDef. Он должен быть списком C-массивов, разделённых запятыми (см. документацию Python по расширениям и встраиванию для получения подробной информации). Операторpymethoddefможет использоваться только внутри блокаpython module.
Атрибуты
Следующие атрибуты могут быть использованы F2PY.
optional-
Соответствующий аргумент перемещается в конец списка
<optional arguments>. Значение по умолчанию для необязательного аргумента можно указать через<init_expr>(см.entitydeclопределение)Примечание
- Значение по умолчанию должно быть задано как допустимое выражение языка C.
- Всякий раз, когда используется
<init_expr>, атрибутoptionalавтоматически устанавливается F2PY. - Для необязательного массива-аргумента все его размерности должны быть ограничены.
required-
Соответствующий аргумент с этим атрибутом считается обязательным. Это значение по умолчанию.
requiredследует указывать только в случае необходимости отключения автоматическойoptionalустановки при использовании<init_expr>.Если в качестве обязательного аргумента используется объект Python
None, аргумент обрабатывается как необязательный. То есть в случае с массивами-аргументами память выделяется. Если задан<init_expr>, то выполняется соответствующая инициализация. dimension(<arrayspec>)-
Соответствующая переменная рассматривается как массив с размерностями, заданными в
<arrayspec>. intent(<intentspec>)-
Это указывает «намерение» соответствующего аргумента.
<intentspec>— это список ключей, разделенных запятыми:-
in-
Соответствующий аргумент считается только входным. Это означает, что значение аргумента передается в функцию Fortran/C, и ожидается, что функция не изменит значение этого аргумента.
-
inout-
Соответствующий аргумент помечен как вход/выход или как in situ аргумент вывода. Аргументы
intent(inout)могут быть только непрерывными массивами NumPy (в смысле Fortran или C) с правильным типом и размером. Последнее совпадает с концепцией непрерывности по умолчанию, используемой в NumPy, и эффективно только если используетсяintent(c). F2PY по умолчанию предполагает непрерывные аргументы Fortran.Примечание
Использование
intent(inout)обычно не рекомендуется, так как это может привести к непредсказуемым результатам. Например, скалярные аргументы, использующиеintent(inout)предполагаются объектами массива, чтобы изменения in situ были эффективными. Используйтеintent(in,out)вместо этого.См. также атрибут
intent(inplace).
-
inplace-
Соответствующий аргумент считается аргументом вход/выход или in situ аргументом вывода. Аргументы
intent(inplace)должны быть массивами NumPy соответствующего размера. Если тип массива не «правильный» или массив не непрерывный, то массив будет изменён на месте для исправления типа и непрерывности.Примечание
Использование
intent(inplace)также не рекомендуется.Например, когда из аргумента
intent(inplace)были взяты срезы, после изменений на месте указатели данных для срезов могут указывать на незарезервированную область памяти.
-
out-
Соответствующий аргумент считается переменной возврата. Он добавляется в список
<returned variables>. Использованиеintent(out)автоматически устанавливаетintent(hide), если не заданыintent(in)илиintent(inout).По умолчанию возвращаемые многомерные массивы являются непрерывными в смысле Fortran. Если используется атрибут
intent(c), то возвращаемые многомерные массивы являются непрерывными в смысле C.
-
hide-
Соответствующий аргумент удаляется из списка обязательных или необязательных аргументов. Обычно
intent(hide)используется сintent(out)или когда значение аргумента полностью определяется<init_expr>, как в следующем примере:integer intent(hide),depend(a) :: n = len(a) real intent(in),dimension(n) :: a
-
c-
Соответствующий аргумент обрабатывается как скалярный или массивный аргумент C. В случае скалярного аргумента его значение передается в функцию C как скалярный аргумент C (напомню, что скалярные аргументы Fortran фактически являются указателями на аргументы C). Для аргументов-массивов предполагается, что функция-обертка обрабатывает многомерные массивы как непрерывные массивы C.
Для одномерных массивов нет необходимости использовать
intent(c), независимо от того, находится ли обернутая функция в Fortran или C. Это связано с тем, что понятия непрерывности Fortran и C совпадают в одномерных случаях.Если
intent(c)используется как оператор, но без списка сущностей, то F2PY добавляет атрибутintent(c)ко всем аргументам.Также при обертывании функций C необходимо использовать атрибут
intent(c)для<routine name>для отключения специфичных для FortranF_FUNC(..,..)макросов.
-
cache-
Соответствующий аргумент рассматривается как мусорная память. Проверки непрерывности Fortran и C не выполняются. Использование
intent(cache)имеет смысл только для аргументов-массивов, также в сочетании с атрибутамиintent(hide)илиoptional.
-
copy-
Гарантирует, что исходное содержимое аргумента
intent(in)сохраняется. Обычно используется с атрибутомintent(in,out). F2PY создаёт необязательный аргументoverwrite_<argument name>со значением по умолчанию0.
-
overwrite-
Это указывает, что исходное содержимое аргумента
intent(in)может быть изменено функцией Fortran/C. F2PY создаёт необязательный аргументoverwrite_<argument name>со значением по умолчанию1.
-
out=<new name>-
Заменяет возвращаемое имя на
<new name>в строке__doc__функции-обертки.
-
callback-
Создает внешнюю функцию, подходящую для вызова функций Python из Fortran.
intent(callback)должно быть указано перед соответствующим операторомexternal. Если 'аргумент' не содержится в списке аргументов, он будет добавлен в оболочку Python, но только путем инициализации внешней функции.Примечание
Используйте
intent(callback)в ситуациях, когда код Fortran/C предполагает, что пользователь реализовал функцию с заданным прототипом и связал её с исполняемым файлом. Не используйтеintent(callback), если функция появляется в списке аргументов Fortran-подпрограммы.При указанных атрибутах
intent(hide)илиoptionalи использовании функции-обертки без указания аргумента обратного вызова в списке аргументов; функция обратного вызова предполагается в пространстве имен сгенерированного F2PY модуля расширения, где она может быть установлена в качестве атрибута модуля пользователем.
-
aux-
Определяет вспомогательную переменную C в сгенерированной F2PY функции-обертки. Полезно для сохранения значений параметров, чтобы к ним можно было обратиться в выражениях инициализации других переменных.
Примечание
intent(aux)молчаливо подразумеваетintent(c).
Применяются следующие правила:
-
Если ни один из
intent(in | inout | out | hide)не указан, предполагаетсяintent(in).-
intent(in,inout)равноintent(in); -
intent(in,hide)илиintent(inout,hide)равноintent(hide); -
intent(out)равноintent(out,hide), если не указаныintent(in)илиintent(inout).
-
-
Если используется
intent(copy)илиintent(overwrite), то вводится дополнительный необязательный аргумент с именемoverwrite_<argument name>и значением по умолчанию 0 или 1 соответственно.-
intent(inout,inplace)равноintent(inplace); -
intent(in,inplace)равноintent(inplace); -
intent(hide)отключаетoptionalиrequired.
-
-
check([<C-booleanexpr>])-
Выполняет проверку согласованности аргументов, вычисляя
<C-booleanexpr>; если<C-booleanexpr>возвращает 0, возникает исключение.Примечание
Если
check(..)не используется, F2PY автоматически генерирует несколько стандартных проверок (например, в случае аргумента-массива проверяется правильная форма и размер). Используйтеcheck()для отключения проверок, сгенерированных F2PY. depend([<names>])-
Объявляет, что соответствующий аргумент зависит от значений переменных в списке
<names>. Например,<init_expr>может использовать значения других аргументов. Используя информацию, предоставленную атрибутамиdepend(..), F2PY гарантирует, что аргументы будут инициализированы в правильном порядке. Если атрибутdepend(..)не используется, F2PY автоматически определяет зависимости. Используйтеdepend()для отключения зависимостей, сгенерированных F2PY.При редактировании зависимостей, первоначально сгенерированных F2PY, будьте осторожны, чтобы не нарушить зависимости других соответствующих переменных. Ещё одна вещь, на которую стоит обратить внимание, — это циклические зависимости. F2PY может обнаружить циклические зависимости при построении оберток и сообщает об этом, если таковые обнаружены.
allocatable-
Соответствующая переменная является массивом Fortran 90, выделенным в данных модуля Fortran 90.
external-
Соответствующий аргумент — функция, предоставляемая пользователем. Подпись этой обратной функции может быть определена
- в блоке модуля
__user__, - или демонстративным (или реальным, если файл подписи — реальный код Fortran) вызовом в блоке
<other statements>.
Например, F2PY генерирует из:
external cb_sub, cb_fun integer n real a(n),r call cb_sub(a,n) r = cb_fun(4)
следующие подписи обратных функций:
subroutine cb_sub(a,n) real dimension(n) :: a integer optional,check(len(a)>=n),depend(a) :: n=len(a) end subroutine cb_sub function cb_fun(e_4_e) result (r) integer :: e_4_e real :: r end function cb_funСоответствующие предоставляемые пользователем функции Python тогда:
def cb_sub(a,[n]): ... return def cb_fun(e_4_e): ... return rСм. также атрибут
intent(callback). - в блоке модуля
parameter-
Это указывает, что соответствующая переменная — параметр, и она должна иметь фиксированное значение. F2PY заменяет все вхождения параметра соответствующими значениями.
Расширения
Директивы F2PY
Директивы F2PY позволяют использовать конструкции файла подписи F2PY в исходном коде Fortran 77/90. С этой функцией можно (почти) полностью пропустить генерацию промежуточного файла подписи и применить F2PY непосредственно к исходному коду Fortran.
Директивы F2PY имеют следующий вид:
<comment char>f2py ...
где разрешённые символы комментариев для кода Fortran с фиксированным и свободным форматом соответственно cC*!# и !, соответственно. Всё, что следует за <comment char>f2py игнорируется компилятором, но считывается F2PY как обычная строка Fortran без комментариев:
Примечание
Когда F2PY находит строку с директивой F2PY, директива сначала заменяется 5 пробелами, а затем строка перечитывается.
Для кода Fortran с фиксированным форматом <comment char> должен быть в первой колонке файла, конечно. Для кода Fortran со свободным форматом директивы F2PY могут появляться где угодно в файле.
Выражения C
Выражения C используются в следующих частях файлов подписи:
-
<init_expr>для инициализации переменных; -
<C-booleanexpr>атрибутаcheck; -
<arrayspec>атрибутаdimension; -
callstatementоператора, здесь также можно использовать многострочный блок C.
Выражение C может содержать:
- стандартные конструкции C;
- функции из
math.hиPython.h; - переменные из списка аргументов, предположительно инициализированные перед этим в соответствии с заданными зависимостями;
-
следующие макросы CPP:
f2py_rank(<name>)-
Возвращает ранг массива
<name>. f2py_shape(<name>, <n>)-
Возвращает
<n>-ю размерность массива<name>. f2py_len(<name>)-
Возвращает длину массива
<name>. f2py_size(<name>)-
Возвращает размер массива
<name>. f2py_itemsize(<name>)-
Возвращает размер элемента массива
<name>. f2py_slen(<name>)-
Возвращает длину строки
<name>.
Для инициализации массива <array name>, F2PY генерирует цикл по всем индексам и размерностям, который выполняет следующее псевдоутверждение:
<array name>(_i[0],_i[1],...) = <init_expr>;
где _i[<i>] относится к <i>-му значению индекса и проходит от 0 до shape(<array name>,<i>)-1.
Например, функция myrange(n) сгенерированная из следующей подписи
subroutine myrange(a,n) fortranname ! myrange is a dummy wrapper integer intent(in) :: n real*8 intent(c,out),dimension(n),depend(n) :: a = _i[0] end subroutine myrange
эквивалентна numpy.arange(n,dtype=float).
Предупреждение
F2PY может также приводить к нижнему регистру выражения C при сканировании кода Fortran (см. опцию --[no]-lower).
Многострочные блоки
Многострочный блок начинается с ''' (тройные одинарные кавычки) и заканчивается ''' в следующей строке. Многострочные блоки могут использоваться только в файлах .pyf. Содержимое многострочного блока может быть произвольным (за исключением того, что оно не может содержать ''') и к нему не применяются никакие преобразования (например, приведение к нижнему регистру).
В настоящее время многострочные блоки могут использоваться в следующих конструкциях:
- в качестве выражения C оператора
callstatement; - в качестве спецификации типа C оператора
callprotoargument; - в качестве блока кода C оператора
usercode; - в качестве списка массивов C оператора
pymethoddef;
- в качестве строки документации.
Расширенный селектор символов
F2PY расширяет спецификацию селектора символов, используемую в файле подписи или директиве F2PY, следующим образом:
<extended-charselector> := <charselector>
| (f2py_len= <len>)
См. Строки символов для использования.
© 2005–2024 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/2.0/f2py/signature-file.html