python3 str对象无法传递PyUnicode_Check

时间:2016-03-24 08:06:40

标签: python c python-3.x python-c-api python-c-extension

我正在编写一个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

据我所知,Python 3的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);
}

1 个答案:

答案 0 :(得分:3)

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