我有一个pxd文件,该文件使用ctypedef声明某些类型,并使用cdef声明某些功能。要调用一个特定的函数,我必须在pyx文件中复制typedef。
如果我将函数的cdef移到pyx文件中,它将无法编译为“无法将'state_t *'转换为Python对象”。错误涉及此行代码
retval = c_explanation.table_of_states_is_bad(<state_t*>test_array, b)
test_array参数是使用malloc在本地创建的,因此根本不是python对象。
如果从pyx文件中删除typedef,并使用from .. import *导入pxd文件中的cdef,我会遇到相同的编译错误。
我可以使这段简单的代码起作用的唯一方法是在pyx和pxd文件中重复进行typedef笨拙的复制。
对这里发生的事情以及如何解决它有任何想法吗?
完整的代码粘贴在下面
pyx文件
from libc.stdlib cimport malloc, free
cimport c_explanation
cdef extern from "explanation.h":
ctypedef int state_id;
ctypedef struct event_t:
pass
ctypedef void (*event_handler)(event_t event)
ctypedef struct state_t:
state_id id
event_handler handle
char *name
ctypedef enum bool:
pass
def table_of_states_is_bad(a, b):
cdef state_t *test_array
cdef bool retval
test_array = <state_t*>malloc(len(a) * sizeof(state_t))
if not test_array:
raise MemoryError()
try:
for i, s in enumerate(a):
test_array[i].id = s[0]
retval = c_explanation.table_of_states_is_bad(test_array, b)
return retval
finally:
free(test_array)
pxd文件
cdef extern from "explanation.h":
cdef int mock_get_temp(int)
ctypedef enum bool:
pass
ctypedef struct event_t:
pass
ctypedef void (*event_handler)(event_t event);
ctypedef int state_id;
ctypedef struct state_t:
state_id id
event_handler handle
char *name
cdef bool table_of_states_is_bad(state_t table[], size_t size)
最后是h文件
int mock_get_temp(int);
typedef int event_id;
/* an event */
typedef struct {
event_id id; /* numeric id */
void *data; /* points to anything */
char *name; /* points to string for debug or log */
} event_t;
typedef void (*event_handler)(event_t event);
typedef enum { false, true } bool;
typedef int state_id;
/* a state */
typedef struct {
state_id id; /* numeric id */
event_handler handle; /* points to handler */
char *name; /* points to string for debug or log */
} state_t;
bool table_of_states_is_bad(state_t table[], size_t size);
答案 0 :(得分:0)
经过一番阅读和实验,我弄清楚了我做错了什么。
问题是名称空间之一。使用import *格式时,table_of_states_is_bad()的本地定义将替换导入的表。因此,函数调用是针对该函数的cython版本,而不是c版本,因此该错误已正确报告。
我通过将本地函数重命名为wrap_table_of_states_is_bad()从而解决了名称冲突。