.pyd和.pyx文件中声明之间的行为差​​异

时间:2018-12-27 10:07:43

标签: cython cythonize

我有一个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);

1 个答案:

答案 0 :(得分:0)

经过一番阅读和实验,我弄清楚了我做错了什么。

问题是名称空间之一。使用import *格式时,table_of_states_is_bad()的本地定义将替换导入的表。因此,函数调用是针对该函数的cython版本,而不是c版本,因此该错误已正确报告。

我通过将本地函数重命名为wrap_table_of_states_is_bad()从而解决了名称冲突。