PyArg_ParseTupleAndKeywords()中的无值PyObject为NULL

2024-06-16 10:25:38 发布

您现在位置:Python中文网/ 问答频道 /正文

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

typedef struct {
    PyObject_HEAD
    rec_rset_t rst;  //need to pass this to C function
} RSet;

rec是指向结构的指针,如下所示:

^{pr2}$

其中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,同时使变量{}为NULL。如果我传递None,我会得到一个分段错误,因为PyArg_ParseTupleAndKeywords"O"选项不处理PyObject的任何值(这与"s"选项不同,如果我们传递的是NULL字符串,我们可以使用"z")。我尝试手动检查Py_None对象,但没有成功。所以目前我在做一些不太优雅的事情,比如:

if(rset->rst == 0x89e8a0)
    rset->rst = NULL;

因为这是我传递None时的rset->rst的值,然后将这个rset->rst传递给cquery函数。 接收扩展类型对象时,如何将None值传递给PyArg_ParseTuple?有没有一种通用的方法?在

编辑:

我错误地检查了Py yu None的rset->;rst的值。检查

if((PyObject *)rset == Py_None)

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


Tags: 对象函数pynone类型iftyperes
1条回答
网友
1楼 · 发布于 2024-06-16 10:25:38

问题是,如果rset设置为Py_None(一个PyObject*),那么只有PyObject_头定义的字段才是有效的;实际上,您已经获得了一个指向非rset的指针。在

与其将rset->;rst设置为NULL(如果rset==Py_None,则可能会修改不该修改的内存),不如修改代码,使其最初引用PyObject*,然后在确定不是Py une后才强制转换为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);

您可能还希望在强制转换为资源集之前显式检查对象类型。(或使用O!,它会为您进行类型验证,但我似乎还记得,它不允许None,在本例中,这是您想要的。)

相关问题 更多 >