跳到内容

fun

lib 中的 fun 声明绑定到 C 函数。

lib C
  # In C: double cos(double x)
  fun cos(value : Float64) : Float64
end

绑定后,该函数在 C 类型中可用,就像它是类方法一样。

C.cos(1.5) # => 0.0707372

如果函数没有参数,则可以省略括号(在调用时也要省略)。

lib C
  fun getch : Int32
end

C.getch

如果返回值类型为 void,则可以省略它。

lib C
  fun srand(seed : UInt32)
end

C.srand(1_u32)

可以绑定到可变参数函数。

lib X
  fun variadic(value : Int32, ...) : Int32
end

X.variadic(1, 2, 3, 4)

请注意,调用 C 函数时没有隐式转换(除了稍后解释的 to_unsafe):您必须传递期望的精确类型。对于整数和浮点数,可以使用各种 to_... 方法。

函数名

lib 定义中的函数名可以以大写字母开头。这与 lib 外部的方法和函数定义不同,后者必须以小写字母开头。

Crystal 中的函数名可以与 C 名不同。以下示例展示了如何在 Crystal 中将 C 函数名 SDL_Init 绑定为 LibSDL.init

lib LibSDL
  fun init = SDL_Init(flags : UInt32) : Int32
end

C 名可以放在引号中,以便能够编写非有效标识符的名称。

lib LLVMIntrinsics
  fun ceil_f32 = "llvm.ceil.f32"(value : Float32) : Float32
end

这也可以用于为 C 函数提供更短、更友好的名称,因为这些函数往往很长,并且通常以库名作为前缀。

C 绑定中的类型

C 绑定中可以使用的有效类型是

  • 基本类型(Int8,...,Int64UInt8,...,UInt64Float32Float64
  • 指针类型(Pointer(Int32),也可以写成 Int32*
  • 静态数组(StaticArray(Int32, 8),也可以写成 Int32[8]
  • 函数类型(Proc(Int32, Int32),也可以写成 Int32 -> Int32
  • 之前声明的其他 structunionenumtypealias
  • Void:没有返回值。
  • NoReturn:与 Void 类似,但编译器知道在该调用之后无法执行任何代码。
  • @[Extern] 注解标记的 Crystal 结构体。

有关 fun 类型中使用的符号,请参阅类型语法

标准库定义了 LibC 库,其中包含对常见 C 类型的别名,例如 intshortsize_t。在绑定中像这样使用它们。

lib MyLib
  fun my_fun(some_size : LibC::SizeT)
end

注意

C char 类型在 Crystal 中是 UInt8,因此 char*const char*UInt8*。Crystal 中的 Char 类型是 Unicode 代码点,因此由四个字节表示,使其类似于 Int32,而不是 UInt8。如有疑问,还可以使用别名 LibC::Char