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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
|
===============
C-API for NumPy
===============
:Author: Travis Oliphant
:Discussions to: `numpy-discussion@python.org`__
:Created: October 2005
__ https://scipy.org/scipylib/mailing-lists.html
The C API of NumPy is (mostly) backward compatible with Numeric.
All of these headers are installed to
``<YOUR_PYTHON_LOCATION>/site-packages/numpy/core/include``
Getting an arrayobject from an arbitrary Python object
======================================================
``PyArray_FromAny(...)``
This function replaces ``PyArray_ContiguousFromObject`` and friends (those
function calls still remain but they are loose wrappers around the
``PyArray_FromAny`` call).
::
static PyObject *
PyArray_FromAny(PyObject *op, PyArray_Descr *dtype, int min_depth,
int max_depth, int requires, PyObject *context)
``op`` : ``PyObject *``
The Python object to "convert" to an array object
``dtype`` : ``PyArray_Descr *``
The desired data-type descriptor. This can be ``NULL``, if the
descriptor should be determined by the object. Unless ``FORCECAST`` is
present in ``flags``, this call will generate an error if the data
type cannot be safely obtained from the object.
``min_depth`` : ``int``
The minimum depth of array needed or 0 if doesn't matter
``max_depth`` : ``int``
The maximum depth of array allowed or 0 if doesn't matter
``requires`` : ``int``
A flag indicating the "requirements" of the returned array. These
are the usual ndarray flags (see `NDArray flags`_ below). In
addition, there are three flags used only for the ``FromAny``
family of functions:
- ``ENSURECOPY``: always copy the array. Returned arrays always
have ``CONTIGUOUS``, ``ALIGNED``, and ``WRITEABLE`` set.
- ``ENSUREARRAY``: ensure the returned array is an ndarray.
- ``FORCECAST``: cause a cast to occur regardless of whether or
not it is safe.
``context`` : ``PyObject *``
If the Python object ``op`` is not a numpy array, but has an
``__array__`` method, context is passed as the second argument to
that method (the first is the typecode). Almost always this
parameter is ``NULL``.
``PyArray_ContiguousFromAny(op, typenum, min_depth, max_depth)`` is
equivalent to ``PyArray_ContiguousFromObject(...)`` (which is still
available), except it will return the subclass if op is already a
subclass of the ndarray. The ``ContiguousFromObject`` version will
always return an ndarray.
Passing Data Type information to C-code
=======================================
All datatypes are handled using the ``PyArray_Descr *`` structure.
This structure can be obtained from a Python object using
``PyArray_DescrConverter`` and ``PyArray_DescrConverter2``. The former
returns the default ``PyArray_LONG`` descriptor when the input object
is None, while the latter returns ``NULL`` when the input object is ``None``.
See the ``arraymethods.c`` and ``multiarraymodule.c`` files for many
examples of usage.
Getting at the structure of the array.
--------------------------------------
You should use the ``#defines`` provided to access array structure portions:
- ``PyArray_DATA(obj)`` : returns a ``void *`` to the array data
- ``PyArray_BYTES(obj)`` : return a ``char *`` to the array data
- ``PyArray_ITEMSIZE(obj)``
- ``PyArray_NDIM(obj)``
- ``PyArray_DIMS(obj)``
- ``PyArray_DIM(obj, n)``
- ``PyArray_STRIDES(obj)``
- ``PyArray_STRIDE(obj,n)``
- ``PyArray_DESCR(obj)``
- ``PyArray_BASE(obj)``
see more in ``arrayobject.h``
NDArray Flags
=============
The ``flags`` attribute of the ``PyArrayObject`` structure contains important
information about the memory used by the array (pointed to by the data member)
This flags information must be kept accurate or strange results and even
segfaults may result.
There are 6 (binary) flags that describe the memory area used by the
data buffer. These constants are defined in ``arrayobject.h`` and
determine the bit-position of the flag. Python exposes a nice attribute-
based interface as well as a dictionary-like interface for getting
(and, if appropriate, setting) these flags.
Memory areas of all kinds can be pointed to by an ndarray, necessitating
these flags. If you get an arbitrary ``PyArrayObject`` in C-code,
you need to be aware of the flags that are set.
If you need to guarantee a certain kind of array
(like ``NPY_CONTIGUOUS`` and ``NPY_BEHAVED``), then pass these requirements into the
PyArray_FromAny function.
``NPY_CONTIGUOUS``
True if the array is (C-style) contiguous in memory.
``NPY_FORTRAN``
True if the array is (Fortran-style) contiguous in memory.
Notice that contiguous 1-d arrays are always both ``NPY_FORTRAN`` contiguous
and C contiguous. Both of these flags can be checked and are convenience
flags only as whether or not an array is ``NPY_CONTIGUOUS`` or ``NPY_FORTRAN``
can be determined by the ``strides``, ``dimensions``, and ``itemsize``
attributes.
``NPY_OWNDATA``
True if the array owns the memory (it will try and free it using
``PyDataMem_FREE()`` on deallocation --- so it better really own it).
These three flags facilitate using a data pointer that is a memory-mapped
array, or part of some larger record array. But, they may have other uses...
``NPY_ALIGNED``
True if the data buffer is aligned for the type and the strides
are multiples of the alignment factor as well. This can be
checked.
``NPY_WRITEABLE``
True only if the data buffer can be "written" to.
``NPY_WRITEBACKIFCOPY``
This is a special flag that is set if this array represents a copy
made because a user required certain flags in ``PyArray_FromAny`` and
a copy had to be made of some other array (and the user asked for
this flag to be set in such a situation). The base attribute then
points to the "misbehaved" array (which is set read_only). If you use
this flag, you are must call ``PyArray_ResolveWritebackIfCopy`` before
deallocating this array (i.e. before calling ``Py_DECREF`` the last time)
which will write the data contents back to the "misbehaved" array (casting
if necessary) and will reset the "misbehaved" array to ``WRITEABLE``. If
the "misbehaved" array was not ``WRITEABLE`` to begin with then
``PyArray_FromAny`` would have returned an error because ``WRITEBACKIFCOPY``
would not have been possible. In error conditions, call
``PyArray_DiscardWritebackIfCopy`` to throw away the scratch buffer, then
``Py_DECREF`` or ``Py_XDECREF``.
``NPY_UPDATEIFCOPY``
Similar to ``NPY_WRITEBACKIFCOPY``, but deprecated since it copied the
contents back when the array is deallocated, which is not explicit and
relies on refcount semantics. Refcount semantics are unreliable on
alternative implementations of python such as PyPy.
``PyArray_UpdateFlags(obj, flags)`` will update the ``obj->flags`` for
``flags`` which can be any of ``NPY_CONTIGUOUS``, ``NPY_FORTRAN``, ``NPY_ALIGNED``, or
``NPY_WRITEABLE``.
Some useful combinations of these flags:
- ``NPY_BEHAVED = NPY_ALIGNED | NPY_WRITEABLE``
- ``NPY_CARRAY = NPY_DEFAULT = NPY_CONTIGUOUS | NPY_BEHAVED``
- ``NPY_CARRAY_RO = NPY_CONTIGUOUS | NPY_ALIGNED``
- ``NPY_FARRAY = NPY_FORTRAN | NPY_BEHAVED``
- ``NPY_FARRAY_RO = NPY_FORTRAN | NPY_ALIGNED``
The macro ``PyArray_CHECKFLAGS(obj, flags)`` can test any combination of flags.
There are several default combinations defined as macros already
(see ``arrayobject.h``)
In particular, there are ``ISBEHAVED``, ``ISBEHAVED_RO``, ``ISCARRAY``
and ``ISFARRAY`` macros that also check to make sure the array is in
native byte order (as determined) by the data-type descriptor.
There are more C-API enhancements which you can discover in the code,
or buy the book (http://www.trelgol.com)
|