跳到內容

fun

funlib 內的宣告會綁定到一個 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 名稱不同。以下範例示範如何將 C 函式名稱 SDL_Init 在 Crystal 中綁定為 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, ..., Int64, UInt8, ..., UInt64, Float32, Float64)
  • 指標型別 (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