过程类型
过程类型在内部是指向过程的指针。 nil 是过程类型变量的允许值。 Nim使用过程类型来实现 函数式 编程技术。
Examples:
- proc printItem(x: int) = ...
- proc forEach(c: proc (x: int) {.cdecl.}) =
- ...
- forEach(printItem) # 无法编译,因为调用约定不同
- type
- OnMouseMove = proc (x, y: int) {.closure.}
- proc onMouseMove(mouseX, mouseY: int) =
- # 有默认的调用约定
- echo "x: ", mouseX, " y: ", mouseY
- proc setOnMouseMove(mouseMoveEvent: OnMouseMove) = discard
- # 可以, 'onMouseMove'有默认的调用约定,它是兼容的
- # 到 'closure':
- 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 。