Numpy 如何从 Python 调用 C 函数

问题描述 投票:0回答:1

由于出于效率考虑,Numpy 使用 C 语言实现,我想了解 Numpy 到底是如何从 Python 调用 C 函数,比如

np.array
,Numpy 源代码的哪一部分负责调用?

我尝试跟踪源代码,

multiarraymodule.c
目录中
numpy/_core/src/multiarray
的C实现,我特别关注:
PyMethodDef array_module_methods[ ]
以获取模块在导入到python时提供的功能的概述,并且我还关注:

PyModuleDef moduledef = {
    PyModuleDef_HEAD_INIT,
    "_multiarray_umath",
    NULL,
    -1,
    array_module_methods,
    NULL,
    NULL,
    NULL,
    NULL
}

这是初始化期间的模块名称。我还观察到:

_multiarray_umath
被导入:
numpy/_core/multiarray.py
,python 模块定义的函数如:

@array_function_from_c_func_and_dispatcher(_multiarray_umath.empty_like)
def empty_like(
    prototype, dtype=None, order=None, subok=None, shape=None, *,device=None)

随后是大量文档和示例,然后返回:

return (prototype,)

我认为这是必须调用 C 函数实现的地方,比如

empty_like()
函数?

python c numpy-ndarray cpython
1个回答
0
投票

Numpy 究竟如何从 Python 调用 C 函数(如

np.array
),Numpy 源代码的哪一部分负责调用?

当您编写

np.array()
时,它们会从您的代码中调用。如果您尝试反汇编
np.array
调用:

import np
import dis

dis.dis("np.array()")

你得到了

  0           0 RESUME                   0

  1           2 LOAD_NAME                0 (np)
              4 LOAD_METHOD              1 (array)
             26 PRECALL                  0
             30 CALL                     0
             40 RETURN_VALUE

只是一个不错的函数调用,仅此而已。现在,如果我们尝试反汇编函数本身,如果它是Python,我们将得到它的字节码,如上所述;但我们不:

dis.dis(np.array)
# => TypeError: don't know how to disassemble builtin_function_or_method objects

因此,Python 对待

np.array
就像对待
math.sin
一样:它是 Python 加载的库中某处的一些二进制代码。具体来说,在我的系统上它位于

site-packages/numpy/core/_multiarray_umath.cpython-311-darwin.so

这个文件是包

numpy.core._multiarray_umath
,它定义了函数
array

from numpy.core._multiarray_umath import array

Python 如何知道将函数

array
与相应的 C 代码关联起来?
_multiarray_umath
模块是使用
PyModule_Create
函数定义的,使用定义
here
作为具有某些方法,即
array_module_methods
,其中:

{"array",
    (PyCFunction)array_array,
    METH_FASTCALL | METH_KEYWORDS, NULL},

定义于here。导入模块后,会在

PYTHONPATH
中的适当位置找到并动态链接具有适当名称的共享库,并且程序可以访问其功能。 Tl;dr:模块
numpy.core._multiarray_umath
是通过
array
中名为
array_array
的共享库绑定到 C 函数
numpy/core/_multiarray_umath...
PYTHONPATH
属性定义的。

所有这些都在使用 C 或 C++ 扩展 Python构建 C 和 C++ 扩展中详细描述。

我们可以验证这确实是我们所了解和喜爱的

numpy.array

import numpy
import numpy.core._multiarray_umath

numpy.core._multiarray_umath.array == numpy.array
# => True

现在,它最终是如何被分配给

numpy.array
的是一系列复杂的导入、getattrs、全局赋值等等,我现在不想尝试追踪,但它与它是如何调用的,也与特定的 C 函数没有任何关系。

© www.soinside.com 2019 - 2024. All rights reserved.