用 C 扩展 Python:将 PyStringObject 转换为 PyIntObject
Extending Python with C: Convert PyStringObject to PyIntObject
用CPython 2.7,可以PyStringObject
object be converted directly to a PyIntObject
吗?
目前,我使用两个函数将 Python 字符串转换为 Python 整数,PyString_AsString
and PyInt_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;
}
这很好用,但我想知道是否可以一步完成转换?
我认为这不会更容易完成 - 您可以使用字符串作为参数调用 int
,但它会是 as contrived。
请注意,您没有检查 pVal
的 return 值 - 如果字符串无法转换为整数,则 NULL 被 returned 并设置异常.
其实你可以直接调用 PyInt_Type
with PyObject_CallFunctionObjArgs
:
pVal = PyObject_CallFunctionObjArgs((PyObject *)&PyInt_Type, pObj, NULL);
但是您需要检查 returned pVal
NULL
。你说 "This works fine" 但如果你使用 "a"
之类的东西(Python String not C char!)作为 pObj
怎么办?我猜这会在您调用 PyObject_Print
.
时出现段错误
通常您需要检查所有 return 值,以防万一出现问题。否则你可能 运行 陷入各种麻烦,例如当你将 NULL
传递给其他函数(分段错误)或 return 设置异常时的值(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
来获得正确的结果。这不仅在 "single step" 中而且没有分支(检查 PyInt_Check
或 PyString_Check
是不必要的,因为这是在 int.__new__
中完成的):
/* 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;
}
用CPython 2.7,可以PyStringObject
object be converted directly to a PyIntObject
吗?
目前,我使用两个函数将 Python 字符串转换为 Python 整数,PyString_AsString
and PyInt_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;
}
这很好用,但我想知道是否可以一步完成转换?
我认为这不会更容易完成 - 您可以使用字符串作为参数调用 int
,但它会是 as contrived。
请注意,您没有检查 pVal
的 return 值 - 如果字符串无法转换为整数,则 NULL 被 returned 并设置异常.
其实你可以直接调用 PyInt_Type
with PyObject_CallFunctionObjArgs
:
pVal = PyObject_CallFunctionObjArgs((PyObject *)&PyInt_Type, pObj, NULL);
但是您需要检查 returned pVal
NULL
。你说 "This works fine" 但如果你使用 "a"
之类的东西(Python String not C char!)作为 pObj
怎么办?我猜这会在您调用 PyObject_Print
.
通常您需要检查所有 return 值,以防万一出现问题。否则你可能 运行 陷入各种麻烦,例如当你将 NULL
传递给其他函数(分段错误)或 return 设置异常时的值(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
来获得正确的结果。这不仅在 "single step" 中而且没有分支(检查 PyInt_Check
或 PyString_Check
是不必要的,因为这是在 int.__new__
中完成的):
/* 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;
}