我正在尝试在 Cython 中编写一个函数来处理一些字符串。在下面的代码中,我尝试将 unicode
str
对象列表(在 Python 3 中)转换为 char*
表,然后使用该表来搜索子字符串。
我找到了Python 2的解决方案here,但这个解决方案依赖于对象
PyString_AsString
,它仅在Python 2中可用,而在Python 3中我们应该使用PyUnicode_AsUTF8
,我在here找到了它。当我尝试使用 PyUnicode_AsUTF8
时,遇到了这个错误:
:31:16:“PyUnicode_AsUTF8”不是常量、变量或函数标识符
我几乎没有主意了。无论我尝试什么都会导致某种错误。
代码
import cython
from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free
from cpython.string cimport PyUnicode_AsUTF8
from libc.string cimport strstr
@cython.boundscheck(False)
def start(itsstr, tokens):
cdef size_t s
cdef size_t t
cdef size_t ns = len(itsstr)
cdef size_t nt = len(tokens)
cdef const char** t_str = _char_table(itsstr, ns)
cdef const char** t_tok = _char_table(tokens, nt)
cdef unicode x
for s in xrange(ns):
for t in xrange(nt):
if strstr(t_str[s], t_tok[t]):
x = itsstr[s]
PyMem_Free(t_str)
PyMem_Free(t_tok)
cdef const char** _char_table(s, const size_t n):
cdef char** t = <char**>PyMem_Malloc(n * sizeof(char*))
cdef size_t i = 0
for i in xrange(n):
temp = PyUnicode_AsUTF8(s[i])
t[i] = temp
return t
Cython 不会将函数
PyUnicode_AsUTF8
包装在 cpython.string 中。所以你必须自己做:
#instead of from cpython.string cimport PyUnicode_AsUTF8
cdef extern from "Python.h":
const char* PyUnicode_AsUTF8(object unicode) except NULL
char * PyUnicode_AsUTF8(...)
,但是在其前面添加 const 也不会干扰旧版本的 Cython。
except NULL
很重要,因此 cython 将自动处理可能的错误(感谢@socketpair)。
在更新的版本中,非常相似的功能
PyUnicode_AsUTF8AndSize
已经被包装并且可以使用。