Это умный, но запутанный трюк!
Следующий код создает cython-array длины 1, потому что память, которую он использует (но не владеет!), Имеет ровно один элемент .
cdef NodeHeapData_t nhd_tmp
<NodeHeapData_t[:1]>(&nhd_tmp)
Теперь cython-array реализует протокол буфера и, таким образом, Cython имеет механизм для создания format
-строки, которая описывает тип элемента, который он содержит.
np.asarray
также использует протокол буфера и может создавать dtype
-объект из format
-строки, которая предоставляется массивом cython.
Вы можете увидеть format-string через:
%%cython
import numpy as np
# Some compound datatypes used below:
cdef struct NodeHeapData_t:
double val
int i1
int i2
# build the corresponding numpy dtype for NodeHeapData
cdef NodeHeapData_t nhd_tmp
NodeHeapData = np.asarray(<NodeHeapData_t[:1]>(&nhd_tmp)).dtype
print("format string:",memoryview(<NodeHeapData_t[:1]>(&nhd_tmp)).format)
print(NodeHeapData )
, что приводит к
format string: T{d:val:i:i1:i:i2:}
[('val', '<f8'), ('i1', '<i4'), ('i2', '<i4')]
Я не могу придумать менее запутанного решения, кроме создания dtype
- объект вручную - что может показаться некрасивым для некоторых типов данных на разных платформах *, но должно быть прямым в большинстве случаев.
*) np.int
- такой проблемный случай c. Легко упустить из виду, что np.int
отображается на long
, а не int
(сбивает с толку, не так ли?).
Например,
memoryview(np.zeros(1, dtype=np.int)).itemsize
оценивается как
- На Windows: 4 (размер
long
в байтах на Windows). - На Linux: 8 (размер
long
в байтах на Linux ).