/
_vector_sentinel.pyx
120 lines (89 loc) · 4.42 KB
/
_vector_sentinel.pyx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
from cython.operator cimport dereference as deref
from cpython.ref cimport Py_INCREF
cimport numpy as np
from ._typedefs cimport DTYPECODE, ITYPECODE, INT32TYPECODE, INT64TYPECODE
np.import_array()
cdef StdVectorSentinel _create_sentinel(vector_typed * vect_ptr):
if vector_typed is vector[DTYPE_t]:
return StdVectorSentinelFloat64.create_for(vect_ptr)
elif vector_typed is vector[INT32TYPE_t]:
return StdVectorSentinelInt32.create_for(vect_ptr)
elif vector_typed is vector[INT64TYPE_t]:
return StdVectorSentinelInt64.create_for(vect_ptr)
else:
return StdVectorSentinelIntP.create_for(vect_ptr)
cdef class StdVectorSentinel:
"""Wraps a reference to a vector which will be deallocated with this object.
When created, the StdVectorSentinel swaps the reference of its internal
vectors with the provided one (vect_ptr), thus making the StdVectorSentinel
manage the provided one's lifetime.
"""
cdef void* get_data(self):
"""Return pointer to data."""
cdef int get_typenum(self):
"""Get typenum for PyArray_SimpleNewFromData."""
cdef class StdVectorSentinelFloat64(StdVectorSentinel):
cdef vector[DTYPE_t] vec
@staticmethod
cdef StdVectorSentinel create_for(vector[DTYPE_t] * vect_ptr):
# This initializes the object directly without calling __init__
# See: https://cython.readthedocs.io/en/latest/src/userguide/extension_types.html#instantiation-from-existing-c-c-pointers # noqa
cdef StdVectorSentinelFloat64 sentinel = StdVectorSentinelFloat64.__new__(StdVectorSentinelFloat64)
sentinel.vec.swap(deref(vect_ptr))
return sentinel
cdef void* get_data(self):
return self.vec.data()
cdef int get_typenum(self):
return DTYPECODE
cdef class StdVectorSentinelIntP(StdVectorSentinel):
cdef vector[ITYPE_t] vec
@staticmethod
cdef StdVectorSentinel create_for(vector[ITYPE_t] * vect_ptr):
# This initializes the object directly without calling __init__
# See: https://cython.readthedocs.io/en/latest/src/userguide/extension_types.html#instantiation-from-existing-c-c-pointers # noqa
cdef StdVectorSentinelIntP sentinel = StdVectorSentinelIntP.__new__(StdVectorSentinelIntP)
sentinel.vec.swap(deref(vect_ptr))
return sentinel
cdef void* get_data(self):
return self.vec.data()
cdef int get_typenum(self):
return ITYPECODE
cdef class StdVectorSentinelInt32(StdVectorSentinel):
cdef vector[INT32TYPE_t] vec
@staticmethod
cdef StdVectorSentinel create_for(vector[INT32TYPE_t] * vect_ptr):
# This initializes the object directly without calling __init__
# See: https://cython.readthedocs.io/en/latest/src/userguide/extension_types.html#instantiation-from-existing-c-c-pointers # noqa
cdef StdVectorSentinelInt32 sentinel = StdVectorSentinelInt32.__new__(StdVectorSentinelInt32)
sentinel.vec.swap(deref(vect_ptr))
return sentinel
cdef void* get_data(self):
return self.vec.data()
cdef int get_typenum(self):
return INT32TYPECODE
cdef class StdVectorSentinelInt64(StdVectorSentinel):
cdef vector[INT64TYPE_t] vec
@staticmethod
cdef StdVectorSentinel create_for(vector[INT64TYPE_t] * vect_ptr):
# This initializes the object directly without calling __init__
# See: https://cython.readthedocs.io/en/latest/src/userguide/extension_types.html#instantiation-from-existing-c-c-pointers # noqa
cdef StdVectorSentinelInt64 sentinel = StdVectorSentinelInt64.__new__(StdVectorSentinelInt64)
sentinel.vec.swap(deref(vect_ptr))
return sentinel
cdef void* get_data(self):
return self.vec.data()
cdef int get_typenum(self):
return INT64TYPECODE
cdef np.ndarray vector_to_nd_array(vector_typed * vect_ptr):
cdef:
np.npy_intp size = deref(vect_ptr).size()
StdVectorSentinel sentinel = _create_sentinel(vect_ptr)
np.ndarray arr = np.PyArray_SimpleNewFromData(
1, &size, sentinel.get_typenum(), sentinel.get_data())
# Makes the numpy array responsible of the life-cycle of its buffer.
# A reference to the StdVectorSentinel will be stolen by the call to
# `PyArray_SetBaseObject` below, so we increase its reference counter.
# See: https://docs.python.org/3/c-api/intro.html#reference-count-details
Py_INCREF(sentinel)
np.PyArray_SetBaseObject(arr, sentinel)
return arr