如何将 Python 字符串列表转换为 wchar_t 的 C 数组?
How to convert Python list of strings into C array of wchar_t?
C 中的源代码如下所示:
typedef wchar_t char_t;
typedef const char_t* const_string_t;
static const_string_t g_symbols[] = { {L"IBM"}, {L"MSFT"}, {L"YHOO"}, {L"C"} };
...
some_c_func(g_symbols)
...
some_c_func 之前在某处声明为:
int some_c_func(const_string_t* symbols)
将 g_symbols 传递给 some_c_func 函数很重要,因此我必须对其进行包装,看起来应该类似于:
ctypedef wchar_t char_t
ctypedef const char_t* const_string_t
def some_py_func(py_list=['a', 'b', 'c']):
g_symbols = ... # some transformation from py_list to g_symbols
some_c_func(g_symbols)
print('Done!')
如有任何帮助,我将不胜感激
从 unicode 对象获取 wchar*
的最简单方法可能是 PyUnicode_AsWideCharString
。 Cython 没有提供定义所以你需要自己做一个合适的cdef extern
:
from libc.stddef cimport wchar_t
from cpython.mem cimport PyMem_Free
cdef extern from "Python.h":
wchat_t* PyUnicode_AsWideCharString(object, Py_ssize_t*) except NULL
def f(string):
cdef wchar_t* c_string = PyUnicode_AsWideCharString(string, NULL)
# use the string
PyMem_Free(<void*>c_string) # you must free it after use
阅读文档以了解您是否应该使用 "size" 参数。
要为 wchar_t*
的数组分配 space,您应该使用 malloc
或 calloc
。当你完成它时,你应该 free
这个 space 。您需要从 malloc
投射
from libc.stdlib cimport malloc, free
cdef wchar_t** strings = <wchar_t**>malloc(sizeof(wchar_t*)*length)
# do something
free(<void*>strings)
确保清理内存以使用 try and finally 的常见模式:
def some_py_func(py_list):
g_symbols = malloc(...)
try:
# loop through py_list getting wchar_t*
# call your C function
finally:
# loop through g_symbols calling PyMem_Free
free(g_symbols)
您需要注意在发生异常时仅在有效(或NULL
)指针上调用PyMem_Free
。请记住,来自 malloc
的内存可能充满任意值,传递给 PyMem_Free
.
是不安全的
感谢@DavidW,但我发现,我认为,更简单的解决方案:
from cpython.mem cimport PyMem_Malloc, PyMem_Free
def some_py_func(py_list=['a', 'b', 'c']):
cdef int number = len(symbols) # get c int of elements
cdef int idx # for faster loops
# create array with dynamic memory allocation
cdef const_string_t *g_symbols = <const_string_t *> PyMem_Malloc(number * sizeof(const_string_t))
# create array with cycle
for idx, sym in enumerate(py_list):
g_symbols[idx] = PyUnicode_AsWideCharString(sym, NULL)
# call c function
some_c_func(g_symbols)
# free memory
for idx in range(number):
PyMem_Free(g_symbols[idx])
PyMem_Free(g_symbols)
print('Done!')
C 中的源代码如下所示:
typedef wchar_t char_t;
typedef const char_t* const_string_t;
static const_string_t g_symbols[] = { {L"IBM"}, {L"MSFT"}, {L"YHOO"}, {L"C"} };
...
some_c_func(g_symbols)
...
some_c_func 之前在某处声明为:
int some_c_func(const_string_t* symbols)
将 g_symbols 传递给 some_c_func 函数很重要,因此我必须对其进行包装,看起来应该类似于:
ctypedef wchar_t char_t
ctypedef const char_t* const_string_t
def some_py_func(py_list=['a', 'b', 'c']):
g_symbols = ... # some transformation from py_list to g_symbols
some_c_func(g_symbols)
print('Done!')
如有任何帮助,我将不胜感激
从 unicode 对象获取 wchar*
的最简单方法可能是 PyUnicode_AsWideCharString
。 Cython 没有提供定义所以你需要自己做一个合适的cdef extern
:
from libc.stddef cimport wchar_t
from cpython.mem cimport PyMem_Free
cdef extern from "Python.h":
wchat_t* PyUnicode_AsWideCharString(object, Py_ssize_t*) except NULL
def f(string):
cdef wchar_t* c_string = PyUnicode_AsWideCharString(string, NULL)
# use the string
PyMem_Free(<void*>c_string) # you must free it after use
阅读文档以了解您是否应该使用 "size" 参数。
要为 wchar_t*
的数组分配 space,您应该使用 malloc
或 calloc
。当你完成它时,你应该 free
这个 space 。您需要从 malloc
from libc.stdlib cimport malloc, free
cdef wchar_t** strings = <wchar_t**>malloc(sizeof(wchar_t*)*length)
# do something
free(<void*>strings)
确保清理内存以使用 try and finally 的常见模式:
def some_py_func(py_list):
g_symbols = malloc(...)
try:
# loop through py_list getting wchar_t*
# call your C function
finally:
# loop through g_symbols calling PyMem_Free
free(g_symbols)
您需要注意在发生异常时仅在有效(或NULL
)指针上调用PyMem_Free
。请记住,来自 malloc
的内存可能充满任意值,传递给 PyMem_Free
.
感谢@DavidW,但我发现,我认为,更简单的解决方案:
from cpython.mem cimport PyMem_Malloc, PyMem_Free
def some_py_func(py_list=['a', 'b', 'c']):
cdef int number = len(symbols) # get c int of elements
cdef int idx # for faster loops
# create array with dynamic memory allocation
cdef const_string_t *g_symbols = <const_string_t *> PyMem_Malloc(number * sizeof(const_string_t))
# create array with cycle
for idx, sym in enumerate(py_list):
g_symbols[idx] = PyUnicode_AsWideCharString(sym, NULL)
# call c function
some_c_func(g_symbols)
# free memory
for idx in range(number):
PyMem_Free(g_symbols[idx])
PyMem_Free(g_symbols)
print('Done!')