我正在寫一個C擴展函數,它應該接受一個str
對象作爲參數。代碼如下所示:python3 str對象無法通過PyUnicode_Check
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。我無法解決這個問題。任何人都可以告訴我我的代碼有什麼問題。
這裏是「蟒蛇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);
}
難道你不需要帶有'u'參數的'PyArg_ParseTuple'嗎?但它的確依賴於方法表中的參數類型(如METH_VARARGS),您還沒有顯示。 – cdarke
是的,事實上,PyArg_parseTupel可以完美解決這個問題。但是在「python cookbook3」中說過,沒有使用PyArg_ParseTuple就有另一種鍛鍊。 – sun
我並沒有想到代碼的任何其他部分可能會出錯,因爲它適用於其他功能。我在問題描述中添加了整個代碼。 – sun