我想在C扩展模块中实现以下Python函数:
def value(x: Optional[int] = None) -> Optional[int]:
if x is None:
# act like a getter
return APIGetValue() # retrieve the value from an external library
# act like a setter
APISetValue(x) # pass the value to an external library
return None
这是到目前为止我得到的:
static PyObject* MyLib_PyValue(PyObject *self, PyObject *args, PyObject *kwargs) {
static char *kwlist[] = { "x", NULL };
int x;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:value", kwlist, &x)) {
return NULL;
}
if (x == NULL) {
return PyLong_FromLong(APIGetValue());
}
APISetValue(x);
Py_RETURN_NONE;
}
使用args调用该函数有效,但是value()
以getter调用时,我得到的1
不是NULL
。我应该如何进行?我对Python的C API不太熟悉。
首先,您不能有NULL int。NULL是指针的东西。由于C类型转换的工作方式以及NULL
宏的定义方式,x == NULL
使用intx
通常会执行以下两项操作之一:它的行为为x == 0
,或者产生编译时错误。
其次,引用Python C API参数解析文档,
与可选参数相对应的C变量应初始化为其默认值-如果未指定可选参数,则PyArg_ParseTuple()不会触及相应C变量的内容。
也是这样PyArg_ParseTupleAndKeywords
。您x
的未初始化,并且PyArg_ParseTupleAndKeywords
没有为其写入值,因此x
在x == NULL
比较中访问的值是未定义的行为。
您需要初始化x
,并且需要使用实际上允许您检测缺失值的类型。这可能意味着声明x
为asPyObject *x = NULL;
并将其传递"|O:value"
给PyArg_ParseTupleAndKeywords
,然后在函数内部很长时间就处理对C的转换,而不是依赖于PyArg_ParseTupleAndKeywords
这样做。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句