监控 C API
**********

在 3.13 版中添加。

一个扩展可能需要与事件监视系统进行交互。 订阅事件和注册回调都可通过在
"sys.monitoring" 中暴露的 Python API 来完成。


生成执行事件
************

下面的函数使得扩展可以在模拟执行 Python 代码时触发监控事件。 这样的函
数都接受一个 "PyMonitoringState" 结构体，其中包含有关事件激活状态的简
明信息以及事件参数 ，此类参数包括代表代码对象的 "PyObject*"、指令偏移
量，有时还包括额外的、事件专属的参数（请参阅 "sys.monitoring" 了解有关
不同事件回调签名的详情）。 "codelike" 参数应为 "types.CodeType" 的实例
或是某个模拟它的类型。

VM 会在触发事件时禁用跟踪，因此用户不需要额外的操作。

监控函数被调用时不应设置异常，除非是下面列出的用于处理当前异常的函数。

type PyMonitoringState

   事件类型状态的表示形式。 它由用户分配，但其内容则由下文描述的监控
   API 函数来维护。

下面的所有函数均在成功时返回 0 并在失败时返回 -1 (同时设置一个异常)。

请参阅 "sys.monitoring" 获取事件的描述。

int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)

   发出 "PY_START" 事件。

int PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)

   发出 "PY_RESUME" 事件。

int PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval)

   发出 "PY_RETURN" 事件。

int PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval)

   发出 "PY_YIELD" 事件。

int PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *callable, PyObject *arg0)

   发出 "CALL" 事件。

int PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, int lineno)

   发出 "LINE" 事件。

int PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset)

   发出 "JUMP" 事件。

int PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset)

   发出 "BRANCH" 事件。

int PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval)

   发出 "C_RETURN" 事件。

int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)

   使用当前（即 "PyErr_GetRaisedException()" 返回的）异常发出
   "PY_THROW" 事件。

int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)

   使用当前（即 "PyErr_GetRaisedException()" 所返回的）异常发出
   "RAISE" 事件。event with the current ).

int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)

   使用当前（即 "PyErr_GetRaisedException()" 所返回的）异常发出
   "C_RAISE" 事件。

int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)

   使用当前（即 "PyErr_GetRaisedException()" 所返回的）异常发出
   "RERAISE" 事件。

int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)

   使用当前（即 "PyErr_GetRaisedException()" 所返回的）异常发出
   "EXCEPTION_HANDLED" 事件。

int PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)

   使用当前（即 "PyErr_GetRaisedException()" 所返回的）异常发出
   "PY_UNWIND" 事件。

int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *value)

   发出 "STOP_ITERATION" 事件。 如果 "value" 是一个 "StopIteration" 实
   例，它将被使用。 在其他情况下，将新建一个 "StopIteration" 实例并以
   "value" 作为其参数。


管理监控状态
============

监控状态可在监控作用域的协助下进行管理。 一个作用域通常对应一个 python
函数。

int PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, Py_ssize_t length)

   Enter a monitored scope. "event_types" is an array of the event IDs
   for events that may be fired from the scope. For example, the ID of
   a "PY_START" event is the value "PY_MONITORING_EVENT_PY_START",
   which is numerically equal to the base-2 logarithm of
   "sys.monitoring.events.PY_START". "state_array" is an array with a
   monitoring state entry for each event in "event_types", it is
   allocated by the user but populated by "PyMonitoring_EnterScope()"
   with information about the activation state of the event. The size
   of "event_types" (and hence also of "state_array") is given in
   "length".

   The "version" argument is a pointer to a value which should be
   allocated by the user together with "state_array" and initialized
   to 0, and then set only by "PyMonitoring_EnterScope()" itelf. It
   allows this function to determine whether event states have changed
   since the previous call, and to return quickly if they have not.

   The scopes referred to here are lexical scopes: a function, class
   or method. "PyMonitoring_EnterScope()" should be called whenever
   the lexical scope is entered. Scopes can be reentered, reusing the
   same *state_array* and *version*, in situations like when emulating
   a recursive Python function. When a code-like's execution is
   paused, such as when emulating a generator, the scope needs to be
   exited and re-entered.

   The macros for *event_types* are:

   +----------------------------------------------------+---------------------------------------+
   | Macro                                              | Event                                 |
   |====================================================|=======================================|
   | PY_MONITORING_EVENT_BRANCH                         | "BRANCH"                              |
   +----------------------------------------------------+---------------------------------------+
   | PY_MONITORING_EVENT_CALL                           | "CALL"                                |
   +----------------------------------------------------+---------------------------------------+
   | PY_MONITORING_EVENT_C_RAISE                        | "C_RAISE"                             |
   +----------------------------------------------------+---------------------------------------+
   | PY_MONITORING_EVENT_C_RETURN                       | "C_RETURN"                            |
   +----------------------------------------------------+---------------------------------------+
   | PY_MONITORING_EVENT_EXCEPTION_HANDLED              | "EXCEPTION_HANDLED"                   |
   +----------------------------------------------------+---------------------------------------+
   | PY_MONITORING_EVENT_INSTRUCTION                    | "INSTRUCTION"                         |
   +----------------------------------------------------+---------------------------------------+
   | PY_MONITORING_EVENT_JUMP                           | "JUMP"                                |
   +----------------------------------------------------+---------------------------------------+
   | PY_MONITORING_EVENT_LINE                           | "LINE"                                |
   +----------------------------------------------------+---------------------------------------+
   | PY_MONITORING_EVENT_PY_RESUME                      | "PY_RESUME"                           |
   +----------------------------------------------------+---------------------------------------+
   | PY_MONITORING_EVENT_PY_RETURN                      | "PY_RETURN"                           |
   +----------------------------------------------------+---------------------------------------+
   | PY_MONITORING_EVENT_PY_START                       | "PY_START"                            |
   +----------------------------------------------------+---------------------------------------+
   | PY_MONITORING_EVENT_PY_THROW                       | "PY_THROW"                            |
   +----------------------------------------------------+---------------------------------------+
   | PY_MONITORING_EVENT_PY_UNWIND                      | "PY_UNWIND"                           |
   +----------------------------------------------------+---------------------------------------+
   | PY_MONITORING_EVENT_PY_YIELD                       | "PY_YIELD"                            |
   +----------------------------------------------------+---------------------------------------+
   | PY_MONITORING_EVENT_RAISE                          | "RAISE"                               |
   +----------------------------------------------------+---------------------------------------+
   | PY_MONITORING_EVENT_RERAISE                        | "RERAISE"                             |
   +----------------------------------------------------+---------------------------------------+
   | PY_MONITORING_EVENT_STOP_ITERATION                 | "STOP_ITERATION"                      |
   +----------------------------------------------------+---------------------------------------+

int PyMonitoring_ExitScope(void)

   Exit the last scope that was entered with
   "PyMonitoring_EnterScope()".
