gpt4 book ai didi

python - Py_InitModule 复制名称但不复制函数指针?

转载 作者:行者123 更新时间:2023-11-30 03:38:55 25 4
gpt4 key购买 nike

当我使用 Py_InitModule 注册回调时,如果我稍后更改结构中的函数指针以指向新函数,则会调用新函数。但是,如果我更改名称,则无法识别新名称。

#include <Python.h>

PyObject* foo1(PyObject *self, PyObject *args)
{
printf("foo1\n");
Py_RETURN_NONE;
}

PyObject* foo2(PyObject *self, PyObject *args)
{
printf("foo2\n");
Py_RETURN_NONE;
}

int main()
{
PyMethodDef methods[] = {
{ "foo", foo1, METH_VARARGS, "foo" },
{ 0, 0, 0, 0 }
};

Py_Initialize();
Py_InitModule("foo", methods);
PyRun_SimpleString("import foo\n");
PyRun_SimpleString("foo.foo()\n");
methods[0].ml_meth = foo2;
PyRun_SimpleString("foo.foo()\n");
methods[0].ml_name = "foo2";
PyRun_SimpleString("foo.foo()\n");
PyRun_SimpleString("foo.foo2()\n");
return 0;
}

这给出了以下输出:

foo1foo2foo2Traceback (most recent call last):  File "", line 1, in AttributeError: 'module' object has no attribute 'foo2'

这似乎是一个非常不一致的行为。当我为 PyMethodDef 方法 使用堆栈变量时,我第一次遇到它,一旦变量超出范围,程序就会崩溃,我仍然试图从 python 调用 C++ 回调。所以我测试了改变指针确实改变了调用哪个函数,即使我没有用另一个 Py_InitModule 调用重新注册它。但同时,更改名称没有这种行为。

到目前为止,我非常确定 PyMethodDef 需要在 python 代码尝试调用方法(即不能是堆栈/局部变量)时存活,但只能是函数指针自己被使用。

这是故意行为还是疏忽?该文档没有提及我能找到的有关 PyMethodDef 生命周期的任何信息。

最佳答案

您看到的不一致是由于函数代码(函数本身的属性)与从模块调用函数的名称(模块的属性(字典中的键))之间的差异引起的.虽然函数名称也存储在函数对象中,但它仅用于 repr 而不是函数的基本属性。

这是有意为之的,因为它允许在不同的地方以不同的名称使用相同的函数对象——如果函数存储在容器中,甚至可以不用名称。如果仅通过更改函数的属性就可以“重命名”它,这是不可能的。

可以使用常规 Python 函数来证明相同的差异,如下所示:

>>> def add(a, b): return a + b
...
>>> def sub(a, b): return a - b
...
>>> add
<function add at 0x7f9383127938> # the function has a name
>>> add.__name__ = 'foo'
>>> add # the name is changed, but...
<function foo at 0x7f9383127938>
>>> foo # the change doesn't affect the module
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined
>>> add.__code__ = sub.__code__ # we can change the code, though
>>> add(2, 2)
0

关于您在评论中提出的问题:方法字段未被复制,因为 Py_InitModule 和相关函数被设计为使用静态分配的结构进行调用,创建其拷贝会浪费空间。不复制它们解释了为什么更改 ml_meth 中的实际 C 回调会更改 Python 可调用对象。

关于python - Py_InitModule 复制名称但不复制函数指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39193366/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com