Файл подписи
Спецификация синтаксиса для файлов подписи (.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 -
Аргумент рассматривается как аргумент вход/выход или аргумент вывода in situ.
intent(inout)аргументы могут быть только «смежными» массивами NumPy с правильным типом и размером. Здесь «смежный» может быть в смысле Fortran или C. Последний совпадает с понятием смежности, используемым в NumPy, и эффективен только при использованииintent(c). По умолчанию предполагается смежность Fortran.Использование
intent(inout)не рекомендуется, используйте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>для отключения специфичных для 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–2020 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/1.19/f2py/signature-file.html