调用路径


🌐 Call paths

当一个符号通过 ffi.dlopen()、library.getFunction() 或 library.getFunctions() 被解析时,Node.js 会为返回的封装选择三种本地调用路径之一。选择依据是声明的签名、当前平台以及当前进程的能力。这个选择在函数创建时完成,一旦确定就不能配置,也无法从 JavaScript 中观察到。

🌐 When a symbol is resolved through ffi.dlopen(), library.getFunction(), or library.getFunctions(), Node.js selects one of three native call paths for the returned wrapper. The selection is based on the declared signature, on the current platform, and on the capabilities of the current process. It is made once when the function is created, cannot be configured, and is not observable from JavaScript.

这些调用路径被设计成对每个 类型名称 接受相同的 JavaScript 值,执行相同的验证,并抛出相同的错误,这样应用就不需要关心某个函数使用了哪条调用路径。它们的区别在于每次调用执行的工作量不同。设置这些路径的目的是为了让常用的签名能够以尽可能低的开销被调用,同时每个支持的签名仍然保持正常工作。

🌐 The call paths are designed to accept the same JavaScript values for each type name, to perform the same validation, and to throw the same errors, so that applications do not need to know which call path a particular function uses. They differ in how much work is done per call. The paths exist so that common signatures can be called with as little overhead as possible while every supported signature keeps working.

Node.js 会按以下顺序尝试调用路径,并使用第一个支持该签名的路径:

🌐 Node.js tries the call paths in the following order and uses the first one that supports the signature:

  1. 快速 API 调用路径 让优化后的 JavaScript 可以通过生成的每个签名的跳板直接调用本地符号。
  2. 共享缓冲区调用路径 会通过预先分配的缓冲区传递参数,而不是每次调用时在 JavaScript 和 C++ 边界之间转换每个参数。
  3. 通用调用路径 会转换 C++ 中的每个参数,然后通过 libffi 调用该符号。这个路径支持所有的签名。

贡献者指南 FFI Fast API 内部机制 详细描述了这些调用路径的实现。

🌐 The contributor guide FFI Fast API internals describes the implementation of these call paths in detail.