Каков механизм CPython для вызова функции Python из кода C? - PullRequest
1 голос
/ 16 марта 2020

Предположим, я пишу расширение CPython C, и внутри него я хочу вызвать некоторую функцию, написанную на Python.

Inte rnet предполагает, что он включает вызов PyObject *PyObject_Call() из расширения C. Это так?

Если это так, я бы хотел понять механизм, задействованный внутри ВМ, для вызова вызываемой функции Python. Я потратил время на просмотр исходного кода PyObject *PyObject_Call(), но не смог полностью понять, что происходит, поэтому руководство будет оценено.

Что из перечисленного верно?

  1. ВМ выдвигает новый кадр стека и т. Д. c. - но затем ждет следующего eval l oop итерации , чтобы естественным образом переключить управление на вызываемую Python функцию

  2. ВМ вызывает new интерпретация байт-кода l oop для немедленной интерпретации вызываемой функции

  3. Что-то еще?

1 Ответ

2 голосов
/ 16 марта 2020

Это 2. Это также тот же механизм, который используется для вызова Python функций из кода Python. Один экземпляр оценки байт-кода l oop используется для каждого Python стекового кадра, а оценка l oop является реентерабельной.

PyObject_Call является подходящей функцией для использования. (Существуют и другие, которые иногда могут быть более удобными, но PyObject_Call общего назначения.) Возможно, у вас возникли проблемы с пониманием того, что он делает, потому что он просто диспетчер. Он делегирует реализации вызываемого объекта оператор вызова функции.

Для обычных Python функциональных объектов вы можете найти это как function_call в Objects/funcobject.c, и вы можете отследить звонки через _PyFunction_FastCallDict и в конечном итоге до PyEval_EvalFrameEx. Это вызывает interp->eval_frame, который по умолчанию к _PyEval_EvalFrameDefault, который содержит оценку байт-кода l oop.

...