Файл сигнатур
Спецификация синтаксиса для файлов сигнатур (.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 -
Соответствующая переменная представляет собой фортрановский 90-й аллокабельный массив, определённый как данные фортрановского 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.18/f2py/signature-file.html