python3 str对象不能通过PyUnicode_Check

python3 str object cannot pass PyUnicode_Check

我正在编写一个 C 扩展函数,它应该接受一个 str 对象作为参数。代码如下所示:

static PyObject *py_print_chars(PyObject *self, PyObject *o) {
PyObject *bytes;
char *s;
if (!PyUnicode_Check(o)) {
    PyErr_SetString(PyExc_TypeError, "Expected string");
    return NULL;
}
bytes = PyUnicode_AsUTF8String(o);
s = PyBytes_AsString(bytes);
print_chars(s);
Py_DECREF(bytes);
Py_RETURN_NONE;
}

但是当我在 python3 控制台中测试模块时,我发现 str 对象无法通过 PyUnicode_Check:

>>> from sample2 import *    
>>> print_chars('Hello world')    
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Expected string

据我所知,Python3的str()类型在C语言中称为PyUnicode,上面的C代码是参考"python cookbook3"Char15.13编写的。我只是无法解决这个问题。谁能告诉我我的代码有什么问题。

这是 "python cookbook3" 所说的:

如果由于某种原因,您直接使用 PyObject * 而不能使用 PyArg_ParseTuple(),以下代码示例显示了如何检查和提取合适的 char * 引用,来自字节和字符串对象:

/* Some Python Object (obtained somehow) */
PyObject *obj;

/* Conversion from bytes */
{
    char *s;
    s = PyBytes_AsString(o);
    if (!s) {
       return NULL;   /* TypeError already raised */
    }
    print_chars(s);
}
/* Conversion to UTF-8 bytes from a string */
{
    PyObject *bytes;
    char *s;
    if (!PyUnicode_Check(obj)) {
        PyErr_SetString(PyExc_TypeError, "Expected string");
        return NULL;
    }
    bytes = PyUnicode_AsUTF8String(obj);
    s = PyBytes_AsString(bytes);
    print_chars(s);
    Py_DECREF(bytes);
}

以及整个代码:

#include "Python.h"
#include "sample.h"

static PyObject *py_print_chars(PyObject *self, PyObject *o) {
    PyObject *bytes;
    char *s;
    if (!PyUnicode_Check(o)) {
        PyErr_SetString(PyExc_TypeError, "Expected string");
        return NULL;
    }
    bytes = PyUnicode_AsUTF8String(o);
    s = PyBytes_AsString(bytes);
    print_chars(s);
    Py_DECREF(bytes);
    Py_RETURN_NONE;
}

/* Module method table */
static PyMethodDef SampleMethods[] = {
    {"print_chars", py_print_chars, METH_VARARGS, "print character"},
    { NULL, NULL, 0, NULL}
};

/* Module structure */
static struct PyModuleDef samplemodule = {
PyModuleDef_HEAD_INIT,
    "sample",
    "A sample module",
    -1,
    SampleMethods
};

/* Module initialization function */
PyMODINIT_FUNC
PyInit_sample2(void) {
    return PyModule_Create(&samplemodule);
}

如果目标是只接受一个参数,则函数 should be declared as METH_O,而不是 METH_VARARGS;前者在不包装的情况下传递单个参数,后者包装在 tuple 中,需要对其进行解压缩或解析才能在其中获取 PyUnicode*