【发布时间】:2011-07-18 10:12:30
【问题描述】:
我有一个 C python 扩展,我想打印一些诊断信息。
我收到一个字符串作为 PyObject*。
获取此对象的字符串表示形式的规范方法是什么,使其可用作 const char *?
更新:澄清强调访问为 const char *。
【问题讨论】:
我有一个 C python 扩展,我想打印一些诊断信息。
我收到一个字符串作为 PyObject*。
获取此对象的字符串表示形式的规范方法是什么,使其可用作 const char *?
更新:澄清强调访问为 const char *。
【问题讨论】:
使用PyObject_Repr(模仿Python的repr函数)或PyObject_Str(模仿str),然后调用PyString_AsString得到char *(你可以并且通常应该将其用作const char*,例如:
PyObject* objectsRepresentation = PyObject_Repr(yourObject);
const char* s = PyString_AsString(objectsRepresentation);
此方法适用于任何PyObject。如果您绝对确定 yourObject 是 Python 字符串而不是其他字符串,例如数字,您可以跳过第一行并执行以下操作:
const char* s = PyString_AsString(yourObject);
【讨论】:
Py_DECREF(objectsRepresentation),因为PyObject_Repr() 会返回一个新的参考!
如果您使用的是 Python 3,以下是正确答案:
static void reprint(PyObject *obj) {
PyObject* repr = PyObject_Repr(obj);
PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "~E~");
const char *bytes = PyBytes_AS_STRING(str);
printf("REPR: %s\n", bytes);
Py_XDECREF(repr);
Py_XDECREF(str);
}
【讨论】:
PyObject 是纯python 字符串怎么办,如何将其转换为const char*?
PyObject_Repr 在您的字符串周围放置单引号。
PyObject_Repr。为了安全起见,您可以使用if(!PyUnicode_CheckExact(obj)){...} 来验证PyObject *obj 确实是PyUnicode_Type。
"~E~" 是什么意思?
"~E~"替换无效字符/数据
如果您只需要在 Python 3 中打印对象,您可以使用以下函数之一:
static void print_str(PyObject *o)
{
PyObject_Print(o, stdout, Py_PRINT_RAW);
}
static void print_repr(PyObject *o)
{
PyObject_Print(o, stdout, 0);
}
【讨论】:
尝试PyObject_Repr(模仿Python 的repr)或PyObject_Str(模仿Python 的str)。
文档:
计算一个字符串表示 对象o。返回字符串 表示成功,NULL 失败。这相当于 Python 表达式 repr(o)。调用者 repr() 内置函数。
【讨论】:
PyObject *module_name; PyUnicode_AsUTF8(module_name)
【讨论】:
对于 python >=3.3:
char* str = PyUnicode_1BYTE_DATA(py_object);
是的,这是一个非常量指针,您可以通过它修改(不可变的)字符串。
【讨论】:
对于任意PyObject*,首先调用
PyObject_Repr() 或 PyObject_Str() 获取 PyUnicode* 对象。
在 Python 3.3 及更高版本中,调用 PyUnicode_AsUTF8AndSize。除了你想要 const char * 的 Python 字符串之外,此函数还需要一个可选地址来存储长度。
Python 字符串是具有显式长度字段的对象,可能包含空字节,而 const char* 本身通常是指向以空字符结尾的 C 字符串的指针。将 Python 字符串转换为 C 字符串是一个潜在的有损操作。因此,所有其他可以从字符串返回 const char* 的 Python C-API 函数都是 deprecated。
如果您不关心如果字符串恰好包含嵌入的空字节而丢失一堆字符串,您可以将NULL 传递给size 参数。例如,
PyObject* foo = PyUnicode_FromStringAndSize("foo\0bar", 7);
printf("As const char*, ignoring length: %s\n",
PyUnicode_AsUTF8AndSize(foo, NULL));
打印
As const char*, ignoring length: foo
但您也可以传入size 变量的地址,以与const char* 一起使用,以确保您获得整个字符串。
PyObject* foo = PyUnicode_FromStringAndSize("foo\0bar", 7);
printf("Including size: ");
size_t size;
const char* data = PyUnicode_AsUTF8AndSize(foo, &size);
fwrite(data, sizeof(data[0]), size, stdout);
putchar('\n');
在我的终端上,输出
$ ./main | cat -v
Including size: foo^@bar
【讨论】: