Py_InitModule复制名称,但不复制函数指针
Py_InitModule copies the name but not the function pointer?
当我使用Py_InitModule
注册回调时,如果我稍后更改结构中的函数指针以指向新函数,则调用新函数。但是,如果我更改了名称,则无法识别新名称。
#include <Python.h>
PyObject* foo1(PyObject *self, PyObject *args)
{
printf("foo1n");
Py_RETURN_NONE;
}
PyObject* foo2(PyObject *self, PyObject *args)
{
printf("foo2n");
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 foon");
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;
}
输出如下:
<>以前foo1foo2foo2回溯(最近一次调用):文件",第1行AttributeError: 'module'对象没有'foo2'属性这似乎是一个非常不一致的行为。我第一次遇到它是在我为PyMethodDef methods
使用堆栈变量时,一旦变量超出作用域,程序就会崩溃,而我仍然试图从python调用c++回调。所以我测试了改变指针确实改变了哪个函数被调用,即使我没有用另一个Py_InitModule
调用重新注册它。但同时,更改名称不具有此行为。
到目前为止,我很确定PyMethodDef
需要活只要python代码试图调用方法(即不能是堆栈/局部变量),但只有函数指针本身被使用。
这是故意的行为,还是疏忽?文档中没有提到任何关于PyMethodDef lifetime的内容
您看到的不一致源于函数代码之间的差异,这是函数本身的属性,而从模块中调用它的名称是模块的属性(其字典中的键)。虽然函数的名称也存储在函数对象中,但它仅用于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可调用对象。
相关文章:
- 为什么默认复制函数在按值发送参数时不调用?
- 在 c++ 中对字符串使用复制函数时打印的垃圾值
- C++复制函数重载导致"must be a nonstatic member function"错误
- 我的 c 字符串复制函数正在损坏其他变量的堆栈
- 在实现和调用时可以复制函数参数名称吗?
- 使用 c++ 复制函数有什么问题
- 如何在C++中省略对不同参数的复制函数定义
- 我正在尝试使用 fread 和 fwrite 来制作复制函数,但根据缓冲区大小,我不断得到奇怪的输出
- 谁复制函数的返回值
- 从STL复制函数以打印出矢量
- 试图在vector类中创建复制函数
- 字符串复制函数中这两个while循环条件的区别
- 检查类是否有复制函数?返回真或假
- 复制函数打印字符串地址,而不是字符串内容
- 对复制函数进行单元测试
- STL复制函数的实现
- Py_InitModule复制名称,但不复制函数指针
- 当派生函数定义了析构函数时,使用复制函数而不是移动函数
- 在编译时复制C/C++函数
- STL:c++中的转换和复制函数问题