math_sin 是通过FUNC1 macro 定义的:
FUNC1(sin, sin, 0,
"sin($module, x, /)\n--\n\n"
"Return the sine of x (measured in radians).")
FUNC1 is defined as:
#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 双精度,调用 sin(arg_as_double),引发根据需要处理异常,或者在将结果返回给调用者之前,使用math_1() 传入的PyFloat_FromDouble 函数包装来自sin() 的双精度返回值。
sin() 这里是the double sin(double x) function defined in 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 中。
或者您可以告诉编译器使用-save-temps 标志将预处理器输出保存到.i 文件:
make clean && make CC="gcc -save-temps"
您会在Modules/mathmodule.i 中找到make_sin。