Файл подписи
Спецификация синтаксиса для файлов подписи (.pyf файлы) заимствована из спецификации языка Fortran 90/95. Почти все стандартные конструкции Fortran 90/95 поддерживаются, как в свободном, так и в фиксированном формате (напоминаем, что Fortran 77 является подмножеством Fortran 90/95). F2PY также вводит некоторые расширения к спецификации языка Fortran 90/95, которые помогают в проектировании интерфейса Fortran к Python, делая его более «питоническим».
Файлы подписи могут содержать произвольный Fortran код (так что Fortran коды могут рассматриваться как файлы подписи). F2PY игнорирует Fortran конструкции, не относящиеся к созданию интерфейса, без сообщений об ошибках. Однако, это также включает синтаксические ошибки. Поэтому будьте внимательны, чтобы не допускать ошибок ;-).
В целом, содержимое файлов подписи регистрозависимое. При сканировании 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>может быть только списком имён. - Операторы использования:
-
Определение части
<use statement>:use <modulename> [ , <rename_list> | , ONLY : <only_list> ]
где
<rename_list> := <local_name> => <use_name> [ , <rename_list> ]
В настоящее время F2PY использует оператор
useтолько для связывания модулей обратного вызова и аргументовexternal(функции обратного вызова), см. Аргументы обратного вызова. - Операторы общего блока:
-
Определение части
<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 statements -
include '<filename>' include "<filename>"
Если файл
<filename>не существует, операторincludeигнорируется. В противном случае файл<filename>включается в файл подписи.includeоператоры могут использоваться в любой части файла подписи, также вне блоков подписи Fortran/C процедур.
-
-
-
implicit statements -
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 statements -
entry <entry name> [([<arguments>])]
F2PY генерирует обёртки для всех имен входа, используя подпись блока процедуры.
Подсказка: оператор
entryможет использоваться для описания подписи произвольной процедуры, позволяя F2PY сгенерировать несколько обёрток из подписи одного блока процедуры. Существуют некоторые ограничения при выполнении этого:fortrannameне может быть использован,callstatementиcallprotoargumentмогут быть использованы только если они верны для всех процедур входа, и т.д.
-
Кроме того, 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>] -
Вы можете использовать произвольный
<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 -
Аргумент рассматривается как аргумент ввода/вывода или аргумент вывода «на месте». Аргументы
intent(inout)могут быть только «смежными» массивами NumPy с правильным типом и размером. Здесь «смежный» может быть либо в смысле Fortran, либо в смысле C. Последний совпадает с понятием «смежности» в NumPy и эффективен только при использованииintent(c). По умолчанию предполагается смежность в смысле Fortran.Использование
intent(inout)обычно не рекомендуется, используйтеintent(in,out)вместо него. См. также атрибутintent(inplace).
-
-
-
inplace -
Аргумент рассматривается как аргумент ввода/вывода или аргумент вывода «на месте». Аргументы
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 как скалярный аргумент языка C (напомню, что скалярные аргументы Fortran фактически являются указателями аргументов языка C). В случае массива аргумента предполагается, что функция-обёртка будет обрабатывать многомерные массивы как C-смежные массивы.
Для одномерных массивов нет необходимости использовать
intent(c), независимо от того, является ли обернутая функция функцией Fortran или C. Это связано с тем, что понятия Fortran-смежности и C-смежности перекрываются в одномерных случаях.Если
intent(c)используется как оператор, но без списка объявления сущности, F2PY добавляет атрибутintent(c)ко всем аргументам.Также при обёртке функций C необходимо использовать атрибут
intent(c)для<routine name>, чтобы отключить специфичные для Fortran макросыF_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. Если ‘argument’ не находится в списке аргументов, он будет добавлен в обёртку 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> of the ``dimensionатрибута; -
callstatementоператора, здесь также может быть использован многострочный блок C.
Выражение C может содержать:
- стандартные конструкции C;
- функции из
math.hиPython.h; - переменные из списка аргументов, предположительно инициализированные до этого согласно заданным зависимостям;
-
следующие макросы CPP:
-
rank(<name>) -
Возвращает ранг массива
<name>. -
shape(<name>,<n>) -
Возвращает
<n>-ую размерность массива<name>. -
len(<name>) -
Возвращает длину массива
<name>. -
size(<name>) -
Возвращает размер массива
<name>. -
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; - как строка документации.
© 2005–2021 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/1.20/f2py/signature-file.html