为什么我不能在`lib`范围内定义函数?

时间:2020-06-25 03:01:43

标签: crystal-lang

例如,此代码无法编译

def double
  x * x
end

lib LibC
  # Error
  def double
    x * x
  end
end

我知道我们可以使用模块,但是我们不能使用与模块和lib相同的LibC名称

lib LibC

end

module LibC
  def double
    x * x
  end
end

这个问题有解决方案吗?

1 个答案:

答案 0 :(得分:4)

为什么这对您来说是个问题? :)

lib定义到外部库的绑定。从技术上讲,它是通过定义链接器将解析的外部符号的功能签名来实现的。此外,它还允许使用C ABI语义定义结构,将外部库接口中使用的一系列常量映射为有用的分组和别名的枚举,以使在绑定定义中将C​​rystal类型映射为C类型更加容易。

绑定库时,此低级lib定义永远不会成为绑定用户的最终结果!相反,您应该至少定义一个薄包装器,以将外部API转换为更惯用的Crystal版本。

因此,假设我们正在编写虚构的libsaucepan的绑定,您将以lib定义开始,也许像这样:

@[Link("saucepan")]
lib LibSaucepan
  alias Pan = Void*
  fun aquire : Pan
  fun add_water(pan : Pan, ml : LibC::Int)
  fun cook(pan : Pan)
  fun is_done(pan : Pan) : LibC::Int
end

您不会在这里停下来,但可以创建一个包装API的类:

class Saucepan
  def initialize
    @pan = LibSaucepan.aquire
  end

  def add_water(ml : Int)
     LibSaucepan.add_water(@pan, LibC::Int.new(ml))
  end

  def done?
    LibSaucepan.is_done(@pan) == 1
  end

  def cook
    LibSaucepan.cook(@pan)

    until done?
      sleep 1
    end
  end

  def heat_water(ml : Int)
    add_water(ml)
    cook
  end
end

您可以在此包装器中放置任何辅助方法:)