2017-03-20 2 views
1

CPython 2.7에서 PyStringObject 개체를 PyIntObject으로 직접 변환 할 수 있습니까?C로 Python 확장 : PyStringObject를 PyIntObject로 변환

현재, 나는 두 가지 기능 PyString_AsStringPyInt_FromString 사용하여 파이썬 정수로 파이썬 문자열을 변환 :

if (PyString_Check(pObj)) { 
    /* Convert the string literal to an integer */ 
    pVal = PyInt_FromString(PyString_AsString(pObj), NULL, 10); 
    printf(" From string: "); 
    PyObject_Print(pVal, stdout, Py_PRINT_RAW); 
    printf("\n"); 
} else if (PyInt_Check(pObj)) { 
    pVal = pObj; 
} else { 
    PyErr_SetString(PyExc_TypeError, "list items must be integer string literals or integers"); 
    return NULL; 
} 

이 잘 작동을하지만, 변환이 단일 단계에서 가능한 경우 궁금 해서요?

답변

1

사실 당신은 단순히 PyObject_CallFunctionObjArgsPyInt_Type를 호출 할 수

pVal = PyObject_CallFunctionObjArgs((PyObject *)&PyInt_Type, pObj, NULL); 

을 당신이이 NULL에 대한 pVal를 돌려 확인해야하지만. 당신은 "이것은 잘 동작한다"라고 말했지만, "a" (파이썬 문자열은 C 숯!)과 같은 것을 pObj과 같이 사용하면 어떨까요? 내 생각 엔 이건 PyObject_Print에 전화하면 세그 폴트됩니다.

일반적으로 잘못 될 가능성이있는 경우 모든 반환 값을 확인해야합니다. 그렇지 않으면 예를 들어 NULL을 다른 함수 (세그먼테이션 결함)에 전달하거나 예외가 설정되면 값을 리턴 할 때 (SystemError)와 같은 모든 종류의 문제가 발생할 수 있습니다. 또한 지점에 따라 참조 횟수가 다릅니다. 나중에이 코드를 처리 할 수도 있지만 일반적으로 두 번째 분기에서 참조 카운트를 증가시켜 나중에 if을 추가 할 필요가 없습니다. 따라서 다음을 사용하여 제안 할 것입니다 :

if (PyString_Check(pObj)) { 
    /* Convert the string literal to an integer */ 
    pVal = PyObject_CallFunctionObjArgs((PyObject *)&PyInt_Type, pObj, NULL); 
    if (pVal == NULL) { 
     return NULL; 
    } 
    printf(" From string: "); 
    PyObject_Print(pVal, stdout, Py_PRINT_RAW); # <-- can this fail? 
    printf("\n"); 
} else if (PyInt_Check(pObj)) { 
    pVal = pObj; 
    /* Increment the reference count so it has the same count as the pVal in the first branch. */ 
    Py_INCREF(pVal); 
} else { 
    PyErr_SetString(PyExc_TypeError, "list items must be integer string literals or integers"); 
    return NULL; 
} 

또는 간단히 말해서 PyInt_Type에 의존하여 올바르게 사용하십시오.

/* Convert pObj to an integer, this is equivalent to int(pObj) and works 
    for integers and strings alike, however other inputs will fail. */ 
pVal = PyObject_CallFunctionObjArgs((PyObject *)&PyInt_Type, pObj, NULL); 
if (pVal == NULL) { 
    return NULL; 
} 
+0

아 좋은 지적, 그러한 함수가 존재한다는 걸 잊었습니다. –

+1

'PyObject_CallFunctionObjArgs' - 정말 멋진 이름입니다. 그래도 말이 되네. –

+0

예, 기억하기 쉽습니다. D – MSeifert

0

나는 훨씬 쉽게 할 수 있다고 생각하지 않는다. 문자열로 매개 변수로 int을 호출 할 수 있지만, as contrived이 될 수있다. 문자열을 정수로 변환 할 수없는 NULL이 반환되며 예외가 설정되어있는 경우 -


pVal의 반환 값을 확인하지 않는 점에 유의 마십시오.

+0

재 : pVal''의 반환 값을 확인 ... 좋은 점을이 단지 "한 단계"에서뿐만 아니라 (즉,이 int.__new__에서 수행 있기 때문에 PyInt_Check 또는 PyString_Check이 불필요한 검사) 지점이없는 것은 아니다 ! 숫자가 없으면 ValueError를 반환하고, 정수가 너무 크면 NULL을 반환합니다. –