RPython 的外部函数接口

目的

本文档描述了 RPython 语言的 FFI,重点关注 C 等低级后端。它描述了如何从 RPython 层声明和调用低级 (C) 函数。

声明低级外部函数

在 RPython 中声明外部 C 函数很容易,但需要注意的是,低级函数使用 低级类型(如 lltype.Signed 或 lltype.Array),并且内存管理必须手动完成。要声明一个函数,我们编写

from rpython.rtyper.lltypesystem import rffi

external_function = rffi.llexternal(name, args, result)

其中

  • name - 函数的 C 级名称(如何呈现)
  • args - 参数的低级类型
  • result - 结果的低级类型

您可以通过传递可选的 compilation_info 参数来传递有关 C 级包含文件、库和源代码的附加信息。

from rpython.rtyper.lltypesystem import rffi
from rpython.translator.tool.cbuild import ExternalCompilationInfo

info = ExternalCompilationInfo(includes=[], libraries=[])

external_function = rffi.llexternal(
  name, args, result, compilation_info=info
  )

有关 ExternalCompilationInfo 的更多信息,请参阅 cbuild

类型

rffi 中,为 C 结构声明了各种类型,例如 CCHARP (char*)、SIZE_T (size_t) 等。有关详细信息,请参阅文件。非原始类型的实例必须手动分配,使用 lltype.malloc 调用,并使用 lltype.free 释放,两者都使用关键字参数 flavor='raw'。有一些辅助函数,例如字符串到 char* 转换器,有关详细信息,请参阅源代码。

注册函数为外部函数

一旦我们提供了外部函数的低级实现,就可以很好地将对某些库函数(如 os.open)的调用包装成此类调用。为此,有一个 register_external 例程,位于 extfunc.py 中,它为声明此类函数提供了良好的 API,传递 llimpl 作为参数,并最终传递 llfakeimpl 作为 llinterp 执行的测试的伪低级实现。