Signature file

签名文件(.pyf文件)的语法规范是从Fortran 90/95语言规范中借用的。几乎所有Fortran 90/95标准结构都被理解,无论是自由和固定格式(回忆Fortran 77是Fortran 90/95的子集)。F2PY还介绍了Fortran 90/95语言规范的一些扩展,帮助设计Fortran到Python接口,使它更加“Pythonic”。

签名文件可以包含任意Fortran代码(以便Fortran代码可以被认为是签名文件)。F2PY默默地忽略与创建接口无关的Fortran构造。但是,这也包括语法错误。所以,小心不要做一个;-)。

一般来说,签名文件的内容区分大小写。当扫描Fortran代码和写入签名文件时,除了多行块或使用--no-lower选项时,F2PY自动降低所有情况。

签名文件的语法如下所示。

Python module block

签名文件可能包含一个(推荐)或更多python 模块块。python 模块块描述了Python / C扩展模块<modulename>module.c生成。

例外:如果<modulename>包含子字符串__user__,则相应的python t4>块描述了所谓的回调函数的签名(参见Call-back arguments)。

python 模块块具有以下结构:

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 routine signatures

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>] ]

Type declarations

&lt; argument / variable 类型 声明&gt;

<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整数。

如果参数没有&lt; argument 类型 声明>,则其类型通过应用implicit规则到其名称。

Statements

属性语句:
The <argument/variable attribute statement> is <argument/variable type declaration> without <typespec>. 此外,在属性语句中,不能使用其他属性,<entitydecl>也可以只是名称列表。
使用语句:

&lt; use 语句&gt;的定义是

use <modulename> [ , <rename_list> | , ONLY : <only_list> ]

哪里

<rename_list> := <local_name> => <use_name> [ , <rename_list> ]

目前F2PY使用use语句仅用于链接回调模块和external参数(回调函数),请参阅Call-back arguments

公共块语句:

The definition of the <common block statement> part is

common / <common name> / <shortentitydecl>

哪里

<shortentitydecl> := <name> [ ( <arrayspec> ) ] [ , <shortentitydecl> ]

如果python 模块块包含两个或多个具有相同名称的common块,则来自附加声明附加。The types of variables in <shortentitydecl> are defined using <argument type declarations>. Note that the corresponding <argument type declarations> may contain array specifications; then you don’t need to specify these in <shortentitydecl>.

其他声明:

&lt; other 语句&gt;部分是指上文未描述的任何其他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> )
    

    如果未使用&lt; variable 类型定义变量,则隐式规则用于确定变量的类型规格(从其名称的第一个字母开始) 声明&gt;默认隐式规则由

    implicit real (a-h,o-z,$_), integer (i-m)
    
  • entry语句
    entry <entry name> [([<arguments>])]
    

    F2PY使用例程块的签名生成所有条目名称的包装器。

    提示:entry语句可用于描述任意例程的签名,允许F2PY从仅一个例程块签名生成多个包装器。在执行此操作时有一些限制:fortranname不能使用,callstatementcallprotoargument只有在它们对所有入口程序有效时才能使用,等等

此外,F2PY引入了以下语句:

  • threadsafe

    使用Py_BEGIN_ALLOW_THREADS ... Py_END_ALLOW_THREADS阻止对Fortran / C函数的调用。

  • callstatement <C-expr|multi-line block>

    &lt; C-expr |多行 块>将F2PY生成的调用语句替换为Fortran / C函数。包装的Fortran / C函数可用作(*f2py_func)要引发异常,请在&lt; C-expr |中设置f2py_success = 0多行 块&gt;

  • callprotoargument &lt; C-typespecs&gt;

    当使用callstatement语句时,F2PY可能不会为Fortran / C函数生成适当的原型(因为<C-expr>可能包含任何函数调用,F2PY无法确定什么应该是正确的原型)。使用这个语句,你可以显式地指定相应原型的参数:

    extern <return type> FUNC_F(<routine name>,<ROUTINE NAME>)(<callprotoargument>);
    
  • fortranname [&lt; actual Fortran / C 例程 name&gt;]

    对于给定的Fortran / C函数,你可以使用任意的&lt; routine name&gt; 然后,您必须指定&lt; actual Fortran / C 例程 name&gt; 这个说法。

    If fortranname statement is used without <actual Fortran/C routine name> then a dummy wrapper is generated.

  • usercode &lt;多行 块&gt;

    当在python 模块块中使用时,给定的C代码将在包装函数定义之前插入到生成的C / API源。这里你可以定义任意C函数,用于初始化可选参数,例如。如果在python 模块块内使用usercode两次,则在定义外部例程之后插入第二个多线块。

    当在&lt; routine singature&gt;内使用时,给定的C代码将在声明变量之后,语句。因此,usercode后续可以包含声明和C语句。

    当在第一个interface块内使用时,给定的C代码将在扩展模块的初始化函数结束时插入。在这里你可以修改扩展模块字典。例如,用于定义附加变量等

  • pymethoddef &lt; multiline 块&gt;

    多行块将被插入到模块方法PyMethodDef -array的定义中。它必须是逗号分隔的C数组列表(有关详细信息,请参阅扩展和嵌入 Python文档)。pymethoddef语句只能在python 模块块中使用。

Attributes

F2PY使用以下属性:

optional

相应的参数移动到&lt;可选 参数&gt;列表的末尾。可选参数的默认值可以指定<init_expr>,请参阅entitydecl定义。请注意,默认值必须作为有效的C表达式给出。

注意,每当使用<init_expr>时,通过F2PY自动设置optional属性。

对于可选的数组参数,其所有维度必须有界。

required

相应的参数被认为是必需的。这是默认值。只有当使用<init_expr>时需要禁用自动optional设置时,才需要指定required

如果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

    参数被视为返回变量。它附加到&lt;返回的 变量>列表。Using intent(out) sets intent(hide) automatically, unless also intent(in) or intent(inout) were used.

    默认情况下,返回的多维数组是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)属性添加到所有参数。

    Also, when wrapping C functions, one must use intent(c) attribute for <routine name> in order to disable Fortran specific F_FUNC(..,..) macros.

  • cache

    参数被视为内存的一个垃圾。不进行Fortran和C邻接检查。使用intent(cache)仅对数组参数有意义,也与intent(hide)optional属性相关。

  • copy

    确保保留intent(in)参数的原始内容。通常与intent(in,out)属性结合使用。F2PY使用默认值0创建可选参数overwrite_&lt; argument name&gt;

  • overwrite

    intent(in)参数的原始内容可能会被Fortran / C函数修改。F2PY使用默认值1创建可选参数overwrite_&lt; argument name&gt;

  • out =&lt; new 名称&gt;

    在包装器函数的__doc__字符串中将&lt; new name>

  • callback

    构造一个适合从Fortran调用Python函数的外部函数。必须在相应的external语句之前指定intent(callback)如果'argument'不在参数列表中,那么它将被添加到Python包装器,但只初始化外部函数。

    在Fortran / C代码假定用户使用给定原型实现函数并将其链接到可执行文件的情况下,使用intent(callback)如果函数出现在Fortran例程的参数列表中,请不要使用intent(callback)

    使用指定的intent(hide)optional属性并使用包装器函数,而不在参数列表中指定回调参数,然后在F2PY生成扩展的命名空间中查找回调函数模块,其中它可以由用户设置为模块属性。

  • aux

    在F2PY生成的包装函数中定义辅助C变量。用于保存参数值,以便可以在其他变量的初始化表达式中访问它们。注意,intent(aux)默示隐含intent(c)

以下规则适用:

  • 如果没有意图(在 | inout | out | 隐藏),则假设为intent(in)
  • intent(in,inout)intent(in)
  • intent(in,hide)intent(inout,hide)intent(hide)
  • intent(out) is intent(out,hide) unless intent(in) or intent(inout) is specified.
  • 如果使用intent(copy)intent(overwrite),则引入附加可选参数,名称为overwrite_&lt; argument name&gt;,默认值为0或1。
  • intent(inout,inplace)intent(inplace)
  • intent(in,inplace)intent(inplace)
  • intent(hide)禁用optionalrequired
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

相应的参数是用户提供的函数。可以定义所谓的回调函数的签名

  • in __user__ module block,
  • 或者通过在&lt;其他 语句&gt;块中的示范性(或真实,如果签名文件是真实的Fortran代码)

例如,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用其相应的值替换所有参数出现。

Extensions

F2PY directives

所谓的F2PY指令允许在Fortran 77/90源代码中使用F2PY签名文件结构。使用此功能,您可以跳过(几乎)完全中间签名文件生成,并将F2PY直接应用于Fortran源代码。

F2PY指令具有以下形式:

<comment char>f2py ...

其中允许固定和自由格式Fortran代码的注释字符分别是cC*!#!&lt; comment char&gt; f2py之后的所有内容都被编译器忽略,但是由F2PY读为正常的Fortran非注释行:

当F2PY找到具有F2PY指令的行时,指令首先被5个空格替换,然后该行被重新读取。

对于固定格式的Fortran代码,当然,&lt; comment char&gt;必须位于文件的第一列。对于免费格式Fortran代码,F2PY指令可以出现在文件中的任何位置。

C expressions

C表达式用于签名文件的以下部分:

  • <init_expr>
  • check属性的<C-booleanexpr>
  • <arrayspec> of the ``dimension attribute;
  • callstatement语句,这里也可以使用C多线块。

C表达式可以包含:

  • 标准C构建体;

  • 函数来自math.hPython.h

  • 来自参数列表的变量,可能根据给定的依赖关系初始化之前;

  • 以下CPP宏:

    rank(<name>)

    返回数组<name>的排名。

    shape(<name>,<n>)

    返回数组<name><n>维。

    len(<name>)

    返回数组<name>的长度。

    size(<name>)

    返回数组<name>的大小。

    slen(<name>)

    返回字符串<name>的长度。

对于初始化数组&lt; array name>,F2PY会在执行以下伪语句的所有索引和维度上生成循环:

<array name>(_i[0],_i[1],...) = <init_expr>;

where _i[<i>] refers to the <i>-th index value and that runs from 0 to 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)

警告

当扫描Fortran代码时(参见--[no]-lower选项),F2PY也可以减少C表达式中的大小写。

Multiline blocks

多行块以'''(三重单引号)开始,并在严格后续行中以'''结尾。多行块只能在.pyf文件中使用。多行块的内容可以是任意的(除了它不能包含'''),并且没有应用任何转换(例如降低大小写)。

目前,可以在以下结构中使用多行块:

  • 作为callstatement语句的C表达式;
  • 作为callprotoargument语句的C类型规范;
  • 作为usercode语句的C代码块;
  • 作为pymethoddef语句的C数组的列表;
  • 作为文档字符串。