接受可选整数的Python C扩展函数
我想在C扩展模块中实现以下Python函数:接受可选整数的Python C扩展函数,python,c,python-c-api,Python,C,Python C Api,我想在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) # pas
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调用函数是可行的,但是当作为getter调用
value()
时,我得到的是1
,而不是NULL
。我应该如何进行?我还不太熟悉Python的C API。首先,不能有NULL int。NULL是指针的东西。由于C类型转换的工作方式以及NULL
宏的定义方式,x==NULL
和intx
通常执行以下两种操作之一:其行为类似于x==0
,或者产生编译时错误
二是引用,
与可选参数对应的C变量应初始化为其默认值-当未指定可选参数时,PyArg_ParseTuple()不会触及相应C变量的内容
这同样适用于PyArg_ParseTupleAndKeywords
。您的x
未初始化,并且PyArg_ParseTupleAndKeywords
没有为其写入值,因此在x==NULL
比较中访问x
的值是未定义的行为
您需要初始化
x
,并且需要使用一种类型,该类型实际上允许您检测缺少的值。这可能意味着将x
声明为PyObject*x=NULL
并将“|O:value”
传递给PyArg_ParseTupleAndKeywords
,然后在函数中处理到C long的转换,而不是依赖PyArg_ParseTupleAndKeywords
来完成。这是最终结果,以防有人需要一个工作片段:
static PyObject* MyLib_PyValue(PyObject *self, PyObject *args, PyObject *kwargs) {
static char *kwlist[] = { "x", NULL };
PyObject *pyX = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:value", kwlist, &pyX)) {
return NULL;
}
if (pyX == NULL) { // getter
return PyLong_FromLong(APIGetValue());
}
// setter
int x = (int)PyLong_AsLong(pyX);
if (PyErr_Occurred()) {
return NULL;
}
if (x < 0) {
PyErr_SetString(PyExc_ValueError, "x must be positive");
return NULL;
}
APISetValue(x);
Py_RETURN_NONE;
}
static PyObject*MyLib\u PyValue(PyObject*self、PyObject*args、PyObject*kwargs){
静态字符*kwlist[]={“x”,NULL};
PyObject*pyX=NULL;
if(!PyArg_ParseTupleAndKeywords(args、kwargs、“|O:value”、kwlist和pyX)){
返回NULL;
}
如果(pyX==NULL){//getter
从long(APIGetValue())返回PyLong_;
}
//塞特
int x=(int)pyX;
如果(Pyrr_发生()){
返回NULL;
}
if(x<0){
PyErr_SetString(PyExc_ValueError,“x必须为正”);
返回NULL;
}
APISetValue(x);
Py_返回_无;
}
太棒了,谢谢你的快速回答!在C和Python C API中完成我的第一步,请容忍愚蠢的问题。