过程类型

过程类型在内部是指向过程的指针。 nil 是过程类型变量的允许值。 Nim使用过程类型来实现 函数式 编程技术。

Examples:

  1. proc printItem(x: int) = ...
  2.  
  3. proc forEach(c: proc (x: int) {.cdecl.}) =
  4. ...
  5.  
  6. forEach(printItem) # 无法编译,因为调用约定不同
  1. type
  2. OnMouseMove = proc (x, y: int) {.closure.}
  3.  
  4. proc onMouseMove(mouseX, mouseY: int) =
  5. # 有默认的调用约定
  6. echo "x: ", mouseX, " y: ", mouseY
  7.  
  8. proc setOnMouseMove(mouseMoveEvent: OnMouseMove) = discard
  9.  
  10. # 可以, 'onMouseMove'有默认的调用约定,它是兼容的
  11. # 到 'closure':
  12. setOnMouseMove(onMouseMove)

过程类型的一个微妙问题是过程的调用约定会影响类型兼容性:过程类型只有在具有相同的调用约定时才是兼容的。 作为一个特殊的扩展,调用约定 nimcall 的过程可以传递给一个参数,该参数需要调用约定 closure 的proc。

Nim支持这些 调用约定:

nimcall 是用于Nim proc 的默认约定。它与 fastcall 相同,但仅适用于支持 fastcall 的C编译器。

  • closure
  • 是缺少任何pragma注释的 过程类型 的默认调用约定。 它表示该过程具有隐藏的隐式形参(环境)。 具有调用约定 closure 的过程变量占用两个机器字:一个用于proc指针,另一个用于指向隐式传递环境的指针。
  • stdcall
  • 这是微软指定的stdcall约定。生成的C过程使用 __stdcall 关键字声明。
  • cdecl
  • cdecl约定意味着过程应使用与C编译器相同的约定。 在Windows下,生成的C过程使用 __cdecl 关键字声明。
  • safecall
  • 这是微软指定的safecall约定。 生成的C过程使用 _safecall 关键字声明。 安全_ 一词指的是所有硬件寄存器都应被推送到硬件堆栈。
  • inline
  • 内联约定意味着调用者不应该调用该过程,而是直接内联其代码。 请注意,Nim不是内联的,而是将其留给C编译器;它生成 __inline 程序。 这只是编译器的一个提示:编译器可能完全忽略它,它可能内联没有标记为 inline 的过程。
  • fastcall
  • Fastcall对不同的C编译器意味着不同的东西,不论C的 __fastcall 意义是什么。
  • syscall
  • 系统调用约定与C中的 __syscall 相同,用于中断。
  • noconv
  • 生成的C代码将没有任何显式调用约定,因此使用C编译器的默认调用约定。 这是必需的,因为Nim对程序的默认调用约定是 fastcall 来提高速度。大多数调用约定仅适用于Windows 32位平台。

默认调用约定是 nimcall ,除非它是内部proc(proc中的proc)。 对于内部过程,无论是否访问其环境,都会执行分析。 如果它这样做,它有调用约定 closure ,否则它有调用约定 nimcall