разница в поведении между объявлениями в файлах .pyd и .pyx - PullRequest
0 голосов
/ 27 декабря 2018

У меня есть файл pxd, который объявляет некоторые типы с помощью ctypedef, а некоторые функции с помощью cdef.Чтобы вызвать одну конкретную функцию, мне нужно продублировать typedefs в моем файле pyx.

Если я переместу cdef функции в файл pyx, он не сможет скомпилировать с «Cannot преобразовать state_t *» в объект Python».Ошибка относится к этой строке кода

retval = c_explanation.table_of_states_is_bad(<state_t*>test_array, b)

Параметр test_array создается локально с помощью malloc, поэтому вообще не является объектом python.

Если удалить typedefs из файла pyx и импортироватьих и cdef из файла pxd с from .. import *, я получаю ту же ошибку компиляции.

Единственный способ заставить этот простой кусочек кода работать - это довольно неловкое дублированиеtypedefs в файлах pyx и pxd.

Есть мысли о том, что здесь происходит и как решить эту проблему?

Полный код вставлен ниже


pyx file

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 голосов
/ 28 декабря 2018

После некоторого чтения и экспериментов я понял, что я сделал неправильно.

Проблема в одном из пространств имен.При использовании формата import * локальное определение table_of_states_is_bad () заменяет импортированное.Таким образом, вызов функции был для версии функции на Cython, а не для версии c, и, следовательно, ошибка была сообщена правильно.

Я решил проблему, переименовав локальную функцию в wrap_table_of_states_is_bad () и, следовательно, разрешив конфликт имен.

...