理解 PyDict_Check 的行为
我最近在玩Python的C接口,觉得挺有意思的。不过今天遇到了一些问题。我有一个Python扩展,它里面有一个函数,期望接收一个或两个字典作为参数。我有点担心自己可能搞错了PyDict_Check
和PyArg_ParseTuple
的用法。下面是一个简单的例子:
static PyObject * doStuffToOtherStuff(MyCustomPyObject *self, PyObject *args) {
char const *fmt = "OO";
PyObject dict1, dict2;
if (!PyArg_ParseTuple(args, fmt, &dict1, &dict2))
return NULL;
int hasDict1 = PyDict_Check(&dict1);
int hasDict2 = PyDict_Check(&dict2);
printf("%d %d\n");
Py_INCREF(Py_None);
return Py_None;
}
当我编译并导入这个扩展后,我这样调用它:
myClass.doStuffToOtherStuff(dict(), None)
我本来期待它打印出 1 0
,但实际上它打印的是 1 1
。而且像这样调用也一样:
myClass.doStuffToOtherStuff(None, None)
myClass.doStuffToOtherStuff(None, dict())
myClass.doStuffToOtherStuff({}, None)
#等等...
如果我把PyDict_Check
改成PyDict_CheckExact
,无论我传什么参数,它都会打印0 0
。
如果有人能给点建议,我会非常感激。
1 个回答
1
PyArg_ParseTuple
函数在处理 O
参数时,需要一个指向 PyObject *
的指针,而不是指向 PyObject
的指针。也就是说,传入的参数类型应该是 PyObject **
。
所以你的代码应该是:
char const *fmt = "OO";
PyObject *dict1, *dict2;
if (!PyArg_ParseTuple(args, fmt, &dict1, &dict2))
return NULL;
int hasDict1 = PyDict_Check(dict1);
int hasDict2 = PyDict_Check(dict2);
// ...