48

我有一个 C python 扩展,我想打印一些诊断信息。

我收到一个字符串作为 PyObject*。

获取此对象的字符串表示形式以使其可用作 const char * 的规范方法是什么?

更新:澄清强调访问为 const char *。

4

7 回答 7

51

使用PyObject_Repr(模仿 Python 的repr函数) 或PyObject_Str(模仿str),然后调用PyString_AsStringget char *(你可以并且通常应该将其用作const char*),例如:

PyObject* objectsRepresentation = PyObject_Repr(yourObject);
const char* s = PyString_AsString(objectsRepresentation);

此方法适用于任何PyObject. 如果您绝对确定yourObject是 Python 字符串而不是其他字符串,例如数字,则可以跳过第一行并执行以下操作:

const char* s = PyString_AsString(yourObject);
于 2011-11-21T16:39:58.930 回答
31

如果您使用的是 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);
}
于 2017-09-13T16:01:21.153 回答
6

如果您只需要在 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);
}
于 2018-08-05T17:54:11.827 回答
4

尝试PyObject_Repr(模仿 Python 的repr)或PyObject_Str(模仿 Python 的str)。

文件:

计算对象 o 的字符串表示。成功时返回字符串表示,失败时返回 NULL。这相当于 Python 表达式 repr(o)。由 repr() 内置函数调用。

于 2011-03-18T19:20:26.880 回答
1

PyObject *module_name; PyUnicode_AsUTF8(模块名称)

于 2020-04-09T07:55:51.457 回答
1

对于 python >=3.3:

char* str = PyUnicode_1BYTE_DATA(py_object);

是的,这是一个非常量指针,您可以通过它修改(不可变)字符串。

于 2021-01-15T10:04:40.990 回答
0

对于任意的PyObject*,首先调用 PyObject_Repr()PyObject_Str()获取PyUnicode*对象。

在 Python 3.3 及更高版本中,调用PyUnicode_AsUTF8AndSize. 除了您想要的 Python 字符串之外const char *,此函数还需要一个可选地址来存储长度。

Python 字符串是具有显式长度字段的对象,可能包含空字节,而 aconst char*本身通常是指向以空字符结尾的 C 字符串的指针。将 Python 字符串转换为 C 字符串是一个潜在的有损操作。因此,所有其他可以const char*从字符串返回 a 的 Python C-API 函数都已弃用

如果您不在乎丢失一堆字符串,如果它恰好包含嵌入的空字节,您可以传递参数NULLsize例如,

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
于 2021-09-11T16:11:22.160 回答