CPython 中从 C 代码调用 Python 函数的机制是什么?

What is the mechanism in CPython for invoking a Python function from C code?

假设我正在写一个 CPython C 扩展,我想在其中调用一些用 Python.

编写的函数

互联网表明它涉及从 C 扩展调用 PyObject *PyObject_Call()。是这样吗?

如果是,我想了解 VM 内部调用所调用的 Python 函数所涉及的机制。我已经花时间浏览 PyObject *PyObject_Call() 的源代码,但无法完全掌握其中的内容,因此不胜感激。

以下哪一项是正确的?

  1. VM 推送新的堆栈帧等 - 但随后等待 下一次 eval 循环迭代 自然地将控制权切换到被调用的 Python函数

  2. VM 调用新的字节码解释循环以便立即解释调用的函数

  3. 还有别的吗?

它是 2。这也是用于从 Python 代码中调用 Python 函数的相同机制。字节码评估循环的一个实例用于每个 Python 堆栈帧,并且评估循环是可重入的。

PyObject_Call 是一个合适的函数。 (还有其他一些,有时可能更方便,但 PyObject_Call 是通用的。)您可能很难理解它的作用,因为它只是一个调度程序。它委托给被调用对象对函数调用运算符的实现。

对于普通的Python函数对象,你可以找到function_call in Objects/funcobject.c, and you can trace the calls down through _PyFunction_FastCallDict and eventually down to PyEval_EvalFrameEx. That calls interp->eval_frame, which defaults to _PyEval_EvalFrameDefault,其中包含字节码计算循环。