Cython: определение внешней структуры вызывает ошибку компилятора - PullRequest
0 голосов
/ 27 января 2019

Я пытаюсь использовать Collections-C в Cython.

Я заметил, что некоторые структуры определены в файле .c, а псевдоним для них - в файле .h.Когда я пытаюсь определить эти структуры в файле .pxd и использовать их в файле .pyx, gcc выдает ошибку: storage size of ‘[...]’ isn’t known.

Мне удалось воспроизвести мою проблему с минимальной настройкой, которая копирует внешнюю библиотеку и мое приложение:

testdef.c

/* Note: I can't change this */
struct bogus_s {
    int x;
    int y;
};

testdef.h

/* Note: I can't change this */
typedef struct bogus_s Bogus;

cytestdef.pxd

# This is my code
cdef extern from 'testdef.h':
    struct bogus_s:
        int x
        int y

    ctypedef bogus_s Bogus

cytestdef.pyx

# This is my code
def fn():
    cdef Bogus n

    n.x = 12
    n.y = 23

    print(n.x)

Если я запускаю cythonize, я получаю

In function ‘__pyx_pf_7sandbox_9cytestdef_fn’:
cytestdef.c:1106:9: error: storage size of ‘__pyx_v_n’ isn’t known
Bogus __pyx_v_n;
      ^~~~~~~~~

Я также получаюта же ошибка, если я использую обозначение ctypedef Bogus: [...], как указано в руководстве Cython .

Что я делаю не так?

Спасибо.

1 Ответ

0 голосов
/ 27 января 2019

Глядя на документацию для вашей библиотеки Collections-C, это непрозрачные структуры, которые вы должны использовать исключительно через указатели (не нужно знать размер, чтобы иметь указатель, в то время как вы делаете это для размещения в стеке) , Выделение этих структур осуществляется в библиотечных функциях.

Чтобы изменить пример для соответствия этому случаю:

 // C file
 int bogus_s_new(struct bogus_s** v) {
     *v = malloc(sizeof(struct bogus_s));
     return (v!=NULL);
 }

 void free_bogus_s(struct bogus_s* v) {
      free(v);
 }

Ваш файл H будет содержать объявления для них, а ваш файл pxd будет содержать оболочки для объявлений. Затем на Cython:

def fn():
    cdef Bogus* n
    if not bogus_s_new(&n):
        return
    try:
        # you CANNOT access x and y since the type is
        # designed to be opaque. Instead you should use
        # the acessor functions defined in the header
        # n.x = 12
        # n.y = 23
    finally:
        free_bogus_s(n)
...