我正在将扩展类型对象传递给Python函数,该函数需要将此类型中的变量传递给C函数我的扩展类型如下:
typedef struct {
PyObject_HEAD
rec_rset_t rst; //need to pass this to C function
} RSet;
rec_rset_t是指向结构的指针,如下所示:
typedef struct rec_rset_s *rec_rset_t;
其中,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);
}
问题是,我希望能够为
None
对象传递RSet
,并使它在C中转换为NULL,同时使变量rst
为NULL如果我通过None
,我会得到一个分段错误,因为"O"
的PyArg_ParseTupleAndKeywords
选项不处理PyObject
的任何值(这与"s"
选项不同,在这里,如果我们传递"z"
字符串,我们可以使用NULL
)我试图手动检查Py_None
对象,但没有成功所以目前我在做一些不太优雅的事情,比如:if(rset->rst == 0x89e8a0)
rset->rst = NULL;
因为这是当我通过
rset->rst
时None
的值,然后把这个rset->rst
传递给cquery
函数。如何在接收扩展类型对象时将
None
值传递给PyArg_ParseTuple
有没有一般的方法来做这件事?编辑:
我错误地检查了rset->rst的值检查
if((PyObject *)rset == Py_None)
计算结果为true,因此是,不处理任何但是值rset->rst(我传递给cquery)不为空,这是我想要的手动设置rset->rst=NULL是唯一的方法吗?
最佳答案
问题是,如果rset设置为Py_None(PyObject*),则只有PyObject_头定义的字段才保证有效;实际上,您已经返回了指向非rset的某个字段的指针。
与其将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!,它为您进行类型验证,但我似乎还记得,在本例中不允许任何类型验证
关于python - 在PyArg_ParseTupleAndKeywords()中,没有将PyObject的值设置为NULL,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18570769/