接受可选整数的Python C扩展功能

马蹄铁

我想在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不太熟悉。

user2357112支持Monica

首先,您不能有NULL int。NULL是指针的东西。由于C类型转换的工作方式以及NULL宏的定义方式,x == NULL使用intx通常会执行以下两项操作之一:它的行为为x == 0,或者产生编译时错误。

其次,引用Python C API参数解析文档

与可选参数相对应的C变量应初始化为其默认值-如果未指定可选参数,则PyArg_ParseTuple()不会触及相应C变量的内容。

也是这样PyArg_ParseTupleAndKeywordsx的未初始化,并且PyArg_ParseTupleAndKeywords没有为其写入值,因此xx == NULL比较中访问的值是未定义的行为。

您需要初始化x,并且需要使用实际上允许您检测缺失值的类型。这可能意味着声明x为asPyObject *x = NULL;并将其传递"|O:value"PyArg_ParseTupleAndKeywords,然后在函数内部很长时间就处理对C的转换,而不是依赖于PyArg_ParseTupleAndKeywords这样做。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章