Я пытаюсь создать функцию на языке cython, которая принимает многоуровневый структурированный массив или массив записей, определяя тип структуры cython. Предположим, что у меня есть данные:
a = np.recarray(3, dtype=[('a', np.float32), ('b', np.int32), ('c', '|S5'), ('d', '|S3')])
a[0] = (1.1, 1, 'this\0', 'to\0')
a[1] = (2.1, 2, 'that\0', 'ta\0')
a[2] = (3.1, 3, 'dogs\0', 'ot\0')
(Примечание: описанная ниже проблема возникает с нулевым терминатором или без него)
Затем у меня есть код cython:
import numpy as np
cimport numpy as np
cdef packed struct tstruct:
np.float32_t a
np.int32_t b
char[5] c
char[3] d
def test_struct(tstruct[:] x):
cdef:
int k
tstruct y
for k in xrange(3):
y = x[k]
print y.a, y.b, y.c, y.d
Когда я пытаюсь запустить test_struct(a)
, я получаю ошибку:
ValueError: Expected a dimension of size 5, got 8
Если в массиве и соответствующей структуре переупорядочены так, что поля, содержащие строки, не смежны друг с другом, тогда функция работает так, как ожидалось. Кажется, что функция Cython не правильно определяет границу между полями c
и d
и думает, что вы проходите в массиве char суммы длин.
За исключением перетасовки данных (что возможно, но не идеально), есть ли другой способ передать повторную запись с фиксированными данными строковой длины в Cython?
Обновление: Это, по-видимому, потенциальная ошибка Cython. См. Следующее обсуждение группы Google Cython, в которой намекает, где возникает проблема:
https://groups.google.com/forum/#!topic/cython-users/TbLbXdi0_h4
Обновление 2: Эта ошибка была исправлена в основной ветке cython в Github по состоянию на 23 февраля 2014 года, и патч планируется включить в v0.20.2: https://github.com/cython/cython/commit/58d9361e0a6d4cb3d4e87775f78e0550c2fea836