2013-09-02 4 views
2

이 유형의 변수를 C 함수에 전달해야하는 Python 함수에 확장 유형 객체를 전달하고 있습니다.None PyArg_ParseTupleAndKeywords()에서 PyObject를 NULL로 설정합니다.

typedef struct rec_rset_s *rec_rset_t; 

따라서 정의 rec_rset_s :

struct rec_rset_s 
{ 
    size_t size; 
    int a,b; 
} 

그래서 나는이

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

rec_rset_t이 같은 구조체에 대한 포인터입니다 : 내 확장 유형은 다음과 같습니다 인수로 RSet 객체를받는 Python 확장 함수.

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 일 rst이 가지고있다. 옵션이 PyArg_ParseTupleAndKeywords 인 경우 PyObject을 처리하지 않으므로 None을 전달하면 세그먼트 화 오류가 발생합니다 (문자열을 전달하는 경우 "z"을 사용할 수있는 "s" 옵션과 다릅니다). Py_None 개체를 수동으로 확인했지만 작동하지 않았습니다. 현재이 같은 매우 우아하지 뭔가를하고 있어요 그래서 :

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

내가 None을 통과 한 다음 cquery 기능이 rset->rst을 통과 할 때 그 rset->rst의 값 이었기 때문에. 확장 유형 개체를받을 때 None 값을 PyArg_ParseTuple으로 전달하는 방법은 무엇입니까? 이것이 수행되는 일반적인 방법이 있습니까?

편집 :

나는 Py_None에 대한 rset-> 첫 번째의 값을 확인 잘못했다. 확인

if((PyObject *)rset == Py_None) 

은 true로 평가되므로 예, 없음이 처리됩니다. 하지만 rset-> rst (cquery에 전달) 값은 NULL이 아니므로 원하는 값입니다. 수동으로 rset-> rst = NULL로 설정하면이 작업을 수행 할 수있는 유일한 방법입니까?

+0

"PyArg_ParseTupleAndKeywords의"O "옵션이 처리하지 않기 때문에 없음 PyObject의 값 "??? AFAIK는 * None *을 처리합니다. – Bakuriu

+0

@ 바큐 리가 맞다, 'O'는 허용하지 않는다. –

+0

@ 바큐 리 고마워, 나는 내 점검에 너무 성급했다. 질문 편집을 참조하십시오. –

답변

2

rset을 Py_None (PyObject *)로 설정하면 PyObject_HEAD 정의 필드 만 유효하다는 것이 문제입니다. 본질적으로 당신은 RSet이 아닌 무언가에 대한 포인터를 얻었습니다.

rset-> rst를 NULL로 설정하는 대신 (rset == Py_None이라면 안되는 메모리를 수정할 수 있음), 처음에는 PyObject *를 참조하도록 코드를 수정해야합니다. 당신은 명시 적으로 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); 

: Py_None 아닌 특정되면 만 RSET *에 캐스트. (또는 당신을 위해 타입 밸리데이션을하는 O!를 사용하되,이 경우에는 None을 허용하지 않습니다.)