Определение функции math_sin в исходном коде CPython? - PullRequest
4 голосов
/ 18 апреля 2019

Я изучаю кодовую базу CPython.

Я хотел бы знать, где я могу найти определение функции math_sin, которая появляется в таблице mathmethods в mathmodule.c:

{"sin",             math_sin,       METH_O,         math_sin_doc}

Выполнение grep "math_sin" -wr в основной папке cpython возвращает только:

Modules/mathmodule.c:    {"sin",             math_sin,       METH_O,         math_sin_doc},

Где я могу найти определение этой функции?

1 Ответ

9 голосов
/ 18 апреля 2019

math_sin определяется с помощью макроса FUNC1 :

FUNC1(sin, sin, 0,
      "sin($module, x, /)\n--\n\n"
      "Return the sine of x (measured in radians).")

, где FUNC1 определяется как :

#define FUNC1(funcname, func, can_overflow, docstring)                  \
    static PyObject * math_##funcname(PyObject *self, PyObject *args) { \
        return math_1(args, func, can_overflow);                            \
    }\
    PyDoc_STRVAR(math_##funcname##_doc, docstring);

поэтому препроцессор расширяет это до:

    static PyObject * math_sin(PyObject *self, PyObject *args) {
        return math_1(args, sin, 0);
    }
    PyDoc_STRVAR(math_sin_doc, "sin($module, x, /)\n--\n\n"
      "Return the sine of x (measured in radians).");

(но затем все в одной строке и с расширением макроса PyDoc_STRVAR)

Таким образом, math_sin(module, args) в основном является вызовом math_1(args, sin, 0), а math_1(args, sin, 0) вызывает math_1_to_whatever(args, sin, PyFloat_FromDouble, 0), который заботится о проверке, что было передано число с плавающей точкой Python, преобразовывая в C double, вызывая sin(arg_as_double), вызывая при необходимости исключения или оборачивая двойное возвращаемое значение из sin() с помощью функции PyFloat_FromDouble, переданной math_1(), перед возвратом этого результата вызывающей стороне.

sin() здесь double sin(double x) функция, определенная в POSIX math.h.

В принципе, вы можете предварительно обработать все исходное дерево Python и вывести вывод в новый каталог; следующее предполагает, что вы успешно создали двоичный файл python, так как он используется для извлечения необходимых флагов включения для gcc:

find . -type d -exec mkdir -p /tmp/processed/{} \;
(export FLAGS=$(./python.exe -m sysconfig | grep PY_CORE_CFLAGS | cut -d\" -f2) && \
 find . -type f \( -name '*.c' -o -name '*.h' \) -exec gcc -E $FLAGS {} -o /tmp/processed/{} \;)

, а затем math_sin появится в /tmp/preprocessed/Modules/mathmodule.c.

Или вы можете указать компилятору сохранять выходные данные препроцессора в .i файлах с флагом -save-temps:

make clean && make CC="gcc -save-temps"

и вы найдете make_sin в Modules/mathmodule.i.

...