Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python PyArg_ParseTupleAndKeywords()中的无值PyObject为NULL_Python_C_Python C Api_Python Extensions - Fatal编程技术网

Python PyArg_ParseTupleAndKeywords()中的无值PyObject为NULL

Python PyArg_ParseTupleAndKeywords()中的无值PyObject为NULL,python,c,python-c-api,python-extensions,Python,C,Python C Api,Python Extensions,我正在将一个扩展类型对象传递给Python函数,该函数需要将这种类型的变量传递给C函数。我的扩展类型如下所示: typedef struct { PyObject_HEAD rec_rset_t rst; //need to pass this to C function } RSet; typedef struct rec_rset_s *rec_rset_t; if(rset->rst == 0x89e8a0) rset->rst = NULL;

我正在将一个扩展类型对象传递给Python函数,该函数需要将这种类型的变量传递给C函数。我的扩展类型如下所示:

typedef struct {
    PyObject_HEAD
    rec_rset_t rst;  //need to pass this to C function
} RSet;
typedef struct rec_rset_s *rec_rset_t;
if(rset->rst == 0x89e8a0)
    rset->rst = NULL;
rec_rset_t是指向结构的指针,如下所示:

typedef struct {
    PyObject_HEAD
    rec_rset_t rst;  //need to pass this to C function
} RSet;
typedef struct rec_rset_s *rec_rset_t;
if(rset->rst == 0x89e8a0)
    rset->rst = NULL;
其中rec_rset_s的定义如下:

struct rec_rset_s
{
  size_t size; 
  int a,b;
}
所以我有一个Python扩展函数,它接收一个RSet对象作为参数

static PyObject*
Recon_query(Recon *self, PyObject *args, PyObject *kwds)
{
    const char  *type;
    RSet        *tmp = PyObject_NEW(RSet, &RSetType);
    rec_rset_t  res;
    static char *kwlist[] = {"type", "rset", NULL};
    if (! PyArg_ParseTupleAndKeywords(args, kwds, "zO", kwlist,
                                      &type, &rset))
      { 
        return NULL;
      }
    res = cquery(self->rcn, type, rset->rst);
    tmp->rst = res;
    return Py_BuildValue("O",tmp);
}
问题是我希望能够为
RSet
对象传递
None
,并使其在C中转换为NULL,以及使变量
rst
为NULL。如果我传递
None
,我会得到一个分段错误,因为
PyArg\u ParseTupleAndKeywords
“O”
选项不处理
PyObject
的任何值(这与
“s”
选项不同,在传递
NULL
字符串时,我们可以使用
“z”
)。我尝试手动检查
Py_None
对象,但没有成功。所以现在我在做一些不太优雅的事情,比如:

typedef struct {
    PyObject_HEAD
    rec_rset_t rst;  //need to pass this to C function
} RSet;
typedef struct rec_rset_s *rec_rset_t;
if(rset->rst == 0x89e8a0)
    rset->rst = NULL;
因为当我传递
None
时,这就是
rset->rst
的值,然后将这个
rset->rst
传递给
cquery
函数。 当接收扩展类型对象时,如何将
None
值传递给
PyArg\u ParseTuple
?有没有一个通用的方法来实现这一点

编辑:

我错误地检查了Py_None的rset->rst值。检查

if((PyObject *)rset == Py_None)

计算结果为true,因此是,不处理任何值。但是值rset->rst(我传递给cquery)不是NULL,这是我想要的。手动设置rset->rst=NULL是唯一的方法吗

问题在于,如果将rset设置为Py_None(PyObject*),则仅保证PyObject_头定义的字段有效;基本上,你得到了一个指向非资源集的指针

您不应该将rset->rst设置为NULL(如果rset==Py_None,则可能会修改不应该修改的内存),而是应该修改代码,使其最初引用PyObject*,然后仅在确定不是Py_None时才强制转换为rset*:

PyObject *rsetobj = NULL;
rec_rset_t rst;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "zO", kwlist,
                                      &type, &rsetobj))
      { 
        return NULL;
      }
if (rsetobj == Py_None)
    rst = NULL;
else
    rst = ((RSet*)rsetobj)->rst;
res = cquery(self->rcn, type, rst);

您可能还希望在强制转换到RSet之前显式检查对象类型。(或者使用O!,它为您进行类型验证,但我似乎记得这不允许进行任何类型验证,在本例中,您希望这样。)

“因为PyArg_ParseTupleAndKeywords的“O”选项不处理PyObject“”的任何值?”???如果它确实处理
None
@Bakuriu是正确的,'O'允许None@Bakuriu谢谢,我检查得太匆忙了。请参见问题编辑。