tmp
/
pip-install-ghxuqwgs
/numpy_78e94bf2b6094bf9a1f3d92042f9bf46
/doc
/source
/user
/c-info.how-to-extend.rst
******************* | |
How to extend NumPy | |
******************* | |
| That which is static and repetitive is boring. That which is dynamic | |
| and random is confusing. In between lies art. | |
| --- *John A. Locke* | |
| Science is a differential equation. Religion is a boundary condition. | |
| --- *Alan Turing* | |
.. _`sec:Writing-an-extension`: | |
Writing an extension module | |
=========================== | |
While the ndarray object is designed to allow rapid computation in | |
Python, it is also designed to be general-purpose and satisfy a wide- | |
variety of computational needs. As a result, if absolute speed is | |
essential, there is no replacement for a well-crafted, compiled loop | |
specific to your application and hardware. This is one of the reasons | |
that numpy includes f2py so that an easy-to-use mechanisms for linking | |
(simple) C/C++ and (arbitrary) Fortran code directly into Python are | |
available. You are encouraged to use and improve this mechanism. The | |
purpose of this section is not to document this tool but to document | |
the more basic steps to writing an extension module that this tool | |
depends on. | |
.. index:: | |
single: extension module | |
When an extension module is written, compiled, and installed to | |
somewhere in the Python path (sys.path), the code can then be imported | |
into Python as if it were a standard python file. It will contain | |
objects and methods that have been defined and compiled in C code. The | |
basic steps for doing this in Python are well-documented and you can | |
find more information in the documentation for Python itself available | |
online at `www.python.org <http://www.python.org>`_ . | |
In addition to the Python C-API, there is a full and rich C-API for | |
NumPy allowing sophisticated manipulations on a C-level. However, for | |
most applications, only a few API calls will typically be used. If all | |
you need to do is extract a pointer to memory along with some shape | |
information to pass to another calculation routine, then you will use | |
very different calls, then if you are trying to create a new array- | |
like type or add a new data type for ndarrays. This chapter documents | |
the API calls and macros that are most commonly used. | |
Required subroutine | |
=================== | |
There is exactly one function that must be defined in your C-code in | |
order for Python to use it as an extension module. The function must | |
be called init{name} where {name} is the name of the module from | |
Python. This function must be declared so that it is visible to code | |
outside of the routine. Besides adding the methods and constants you | |
desire, this subroutine must also contain calls to import_array() | |
and/or import_ufunc() depending on which C-API is needed. Forgetting | |
to place these commands will show itself as an ugly segmentation fault | |
(crash) as soon as any C-API subroutine is actually called. It is | |
actually possible to have multiple init{name} functions in a single | |
file in which case multiple modules will be defined by that file. | |
However, there are some tricks to get that to work correctly and it is | |
not covered here. | |
A minimal ``init{name}`` method looks like: | |
.. code-block:: c | |
PyMODINIT_FUNC | |
init{name}(void) | |
{ | |
(void)Py_InitModule({name}, mymethods); | |
import_array(); | |
} | |
The mymethods must be an array (usually statically declared) of | |
PyMethodDef structures which contain method names, actual C-functions, | |
a variable indicating whether the method uses keyword arguments or | |
not, and docstrings. These are explained in the next section. If you | |
want to add constants to the module, then you store the returned value | |
from Py_InitModule which is a module object. The most general way to | |
add itmes to the module is to get the module dictionary using | |
PyModule_GetDict(module). With the module dictionary, you can add | |
whatever you like to the module manually. An easier way to add objects | |
to the module is to use one of three additional Python C-API calls | |
that do not require a separate extraction of the module dictionary. | |
These are documented in the Python documentation, but repeated here | |
for convenience: | |
.. cfunction:: int PyModule_AddObject(PyObject* module, char* name, PyObject* value) | |
.. cfunction:: int PyModule_AddIntConstant(PyObject* module, char* name, long value) | |
.. cfunction:: int PyModule_AddStringConstant(PyObject* module, char* name, char* value) | |
All three of these functions require the *module* object (the | |
return value of Py_InitModule). The *name* is a string that | |
labels the value in the module. Depending on which function is | |
called, the *value* argument is either a general object | |
(:cfunc:`PyModule_AddObject` steals a reference to it), an integer | |
constant, or a string constant. | |
Defining functions | |
================== | |
The second argument passed in to the Py_InitModule function is a | |
structure that makes it easy to to define functions in the module. In | |
the example given above, the mymethods structure would have been | |
defined earlier in the file (usually right before the init{name} | |
subroutine) to: | |
.. code-block:: c | |
static PyMethodDef mymethods[] = { | |
{ nokeywordfunc,nokeyword_cfunc, | |
METH_VARARGS, | |
Doc string}, | |
{ keywordfunc, keyword_cfunc, | |
METH_VARARGS|METH_KEYWORDS, | |
Doc string}, | |
{NULL, NULL, 0, NULL} /* Sentinel */ | |
} | |
Each entry in the mymethods array is a :ctype:`PyMethodDef` structure | |
containing 1) the Python name, 2) the C-function that implements the | |
function, 3) flags indicating whether or not keywords are accepted for | |
this function, and 4) The docstring for the function. Any number of | |
functions may be defined for a single module by adding more entries to | |
this table. The last entry must be all NULL as shown to act as a | |
sentinel. Python looks for this entry to know that all of the | |
functions for the module have been defined. | |
The last thing that must be done to finish the extension module is to | |
actually write the code that performs the desired functions. There are | |
two kinds of functions: those that don't accept keyword arguments, and | |
those that do. | |
Functions without keyword arguments | |
----------------------------------- | |
Functions that don't accept keyword arguments should be written as: | |
.. code-block:: c | |
static PyObject* | |
nokeyword_cfunc (PyObject *dummy, PyObject *args) | |
{ | |
/* convert Python arguments */ | |
/* do function */ | |
/* return something */ | |
} | |
The dummy argument is not used in this context and can be safely | |
ignored. The *args* argument contains all of the arguments passed in | |
to the function as a tuple. You can do anything you want at this | |
point, but usually the easiest way to manage the input arguments is to | |
call :cfunc:`PyArg_ParseTuple` (args, format_string, | |
addresses_to_C_variables...) or :cfunc:`PyArg_UnpackTuple` (tuple, "name" , | |
min, max, ...). A good description of how to use the first function is | |
contained in the Python C-API reference manual under section 5.5 | |
(Parsing arguments and building values). You should pay particular | |
attention to the "O&" format which uses converter functions to go | |
between the Python object and the C object. All of the other format | |
functions can be (mostly) thought of as special cases of this general | |
rule. There are several converter functions defined in the NumPy C-API | |
that may be of use. In particular, the :cfunc:`PyArray_DescrConverter` | |
function is very useful to support arbitrary data-type specification. | |
This function transforms any valid data-type Python object into a | |
:ctype:`PyArray_Descr *` object. Remember to pass in the address of the | |
C-variables that should be filled in. | |
There are lots of examples of how to use :cfunc:`PyArg_ParseTuple` | |
throughout the NumPy source code. The standard usage is like this: | |
.. code-block:: c | |
PyObject *input; | |
PyArray_Descr *dtype; | |
if (!PyArg_ParseTuple(args, "OO&", &input, | |
PyArray_DescrConverter, | |
&dtype)) return NULL; | |
It is important to keep in mind that you get a *borrowed* reference to | |
the object when using the "O" format string. However, the converter | |
functions usually require some form of memory handling. In this | |
example, if the conversion is successful, *dtype* will hold a new | |
reference to a :ctype:`PyArray_Descr *` object, while *input* will hold a | |
borrowed reference. Therefore, if this conversion were mixed with | |
another conversion (say to an integer) and the data-type conversion | |
was successful but the integer conversion failed, then you would need | |
to release the reference count to the data-type object before | |
returning. A typical way to do this is to set *dtype* to ``NULL`` | |
before calling :cfunc:`PyArg_ParseTuple` and then use :cfunc:`Py_XDECREF` | |
on *dtype* before returning. | |
After the input arguments are processed, the code that actually does | |
the work is written (likely calling other functions as needed). The | |
final step of the C-function is to return something. If an error is | |
encountered then ``NULL`` should be returned (making sure an error has | |
actually been set). If nothing should be returned then increment | |
:cdata:`Py_None` and return it. If a single object should be returned then | |
it is returned (ensuring that you own a reference to it first). If | |
multiple objects should be returned then you need to return a tuple. | |
The :cfunc:`Py_BuildValue` (format_string, c_variables...) function makes | |
it easy to build tuples of Python objects from C variables. Pay | |
special attention to the difference between 'N' and 'O' in the format | |
string or you can easily create memory leaks. The 'O' format string | |
increments the reference count of the :ctype:`PyObject *` C-variable it | |
corresponds to, while the 'N' format string steals a reference to the | |
corresponding :ctype:`PyObject *` C-variable. You should use 'N' if you ave | |
already created a reference for the object and just want to give that | |
reference to the tuple. You should use 'O' if you only have a borrowed | |
reference to an object and need to create one to provide for the | |
tuple. | |
Functions with keyword arguments | |
-------------------------------- | |
These functions are very similar to functions without keyword | |
arguments. The only difference is that the function signature is: | |
.. code-block:: c | |
static PyObject* | |
keyword_cfunc (PyObject *dummy, PyObject *args, PyObject *kwds) | |
{ | |
... | |
} | |
The kwds argument holds a Python dictionary whose keys are the names | |
of the keyword arguments and whose values are the corresponding | |
keyword-argument values. This dictionary can be processed however you | |
see fit. The easiest way to handle it, however, is to replace the | |
:cfunc:`PyArg_ParseTuple` (args, format_string, addresses...) function with | |
a call to :cfunc:`PyArg_ParseTupleAndKeywords` (args, kwds, format_string, | |
char \*kwlist[], addresses...). The kwlist parameter to this function | |
is a ``NULL`` -terminated array of strings providing the expected | |
keyword arguments. There should be one string for each entry in the | |
format_string. Using this function will raise a TypeError if invalid | |
keyword arguments are passed in. | |
For more help on this function please see section 1.8 (Keyword | |
Paramters for Extension Functions) of the Extending and Embedding | |
tutorial in the Python documentation. | |
Reference counting | |
------------------ | |
The biggest difficulty when writing extension modules is reference | |
counting. It is an important reason for the popularity of f2py, weave, | |
Cython, ctypes, etc.... If you mis-handle reference counts you can get | |
problems from memory-leaks to segmentation faults. The only strategy I | |
know of to handle reference counts correctly is blood, sweat, and | |
tears. First, you force it into your head that every Python variable | |
has a reference count. Then, you understand exactly what each function | |
does to the reference count of your objects, so that you can properly | |
use DECREF and INCREF when you need them. Reference counting can | |
really test the amount of patience and diligence you have towards your | |
programming craft. Despite the grim depiction, most cases of reference | |
counting are quite straightforward with the most common difficulty | |
being not using DECREF on objects before exiting early from a routine | |
due to some error. In second place, is the common error of not owning | |
the reference on an object that is passed to a function or macro that | |
is going to steal the reference ( *e.g.* :cfunc:`PyTuple_SET_ITEM`, and | |
most functions that take :ctype:`PyArray_Descr` objects). | |
.. index:: | |
single: reference counting | |
Typically you get a new reference to a variable when it is created or | |
is the return value of some function (there are some prominent | |
exceptions, however --- such as getting an item out of a tuple or a | |
dictionary). When you own the reference, you are responsible to make | |
sure that :cfunc:`Py_DECREF` (var) is called when the variable is no | |
longer necessary (and no other function has "stolen" its | |
reference). Also, if you are passing a Python object to a function | |
that will "steal" the reference, then you need to make sure you own it | |
(or use :cfunc:`Py_INCREF` to get your own reference). You will also | |
encounter the notion of borrowing a reference. A function that borrows | |
a reference does not alter the reference count of the object and does | |
not expect to "hold on "to the reference. It's just going to use the | |
object temporarily. When you use :cfunc:`PyArg_ParseTuple` or | |
:cfunc:`PyArg_UnpackTuple` you receive a borrowed reference to the | |
objects in the tuple and should not alter their reference count inside | |
your function. With practice, you can learn to get reference counting | |
right, but it can be frustrating at first. | |
One common source of reference-count errors is the :cfunc:`Py_BuildValue` | |
function. Pay careful attention to the difference between the 'N' | |
format character and the 'O' format character. If you create a new | |
object in your subroutine (such as an output array), and you are | |
passing it back in a tuple of return values, then you should most- | |
likely use the 'N' format character in :cfunc:`Py_BuildValue`. The 'O' | |
character will increase the reference count by one. This will leave | |
the caller with two reference counts for a brand-new array. When the | |
variable is deleted and the reference count decremented by one, there | |
will still be that extra reference count, and the array will never be | |
deallocated. You will have a reference-counting induced memory leak. | |
Using the 'N' character will avoid this situation as it will return to | |
the caller an object (inside the tuple) with a single reference count. | |
.. index:: | |
single: reference counting | |
Dealing with array objects | |
========================== | |
Most extension modules for NumPy will need to access the memory for an | |
ndarray object (or one of it's sub-classes). The easiest way to do | |
this doesn't require you to know much about the internals of NumPy. | |
The method is to | |
1. Ensure you are dealing with a well-behaved array (aligned, in machine | |
byte-order and single-segment) of the correct type and number of | |
dimensions. | |
1. By converting it from some Python object using | |
:cfunc:`PyArray_FromAny` or a macro built on it. | |
2. By constructing a new ndarray of your desired shape and type | |
using :cfunc:`PyArray_NewFromDescr` or a simpler macro or function | |
based on it. | |
2. Get the shape of the array and a pointer to its actual data. | |
3. Pass the data and shape information on to a subroutine or other | |
section of code that actually performs the computation. | |
4. If you are writing the algorithm, then I recommend that you use the | |
stride information contained in the array to access the elements of | |
the array (the :cfunc:`PyArray_GETPTR` macros make this painless). Then, | |
you can relax your requirements so as not to force a single-segment | |
array and the data-copying that might result. | |
Each of these sub-topics is covered in the following sub-sections. | |
Converting an arbitrary sequence object | |
--------------------------------------- | |
The main routine for obtaining an array from any Python object that | |
can be converted to an array is :cfunc:`PyArray_FromAny`. This | |
function is very flexible with many input arguments. Several macros | |
make it easier to use the basic function. :cfunc:`PyArray_FROM_OTF` is | |
arguably the most useful of these macros for the most common uses. It | |
allows you to convert an arbitrary Python object to an array of a | |
specific builtin data-type ( *e.g.* float), while specifying a | |
particular set of requirements ( *e.g.* contiguous, aligned, and | |
writeable). The syntax is | |
.. cfunction:: PyObject *PyArray_FROM_OTF(PyObject* obj, int typenum, int requirements) | |
Return an ndarray from any Python object, *obj*, that can be | |
converted to an array. The number of dimensions in the returned | |
array is determined by the object. The desired data-type of the | |
returned array is provided in *typenum* which should be one of the | |
enumerated types. The *requirements* for the returned array can be | |
any combination of standard array flags. Each of these arguments | |
is explained in more detail below. You receive a new reference to | |
the array on success. On failure, ``NULL`` is returned and an | |
exception is set. | |
*obj* | |
The object can be any Python object convertable to an ndarray. | |
If the object is already (a subclass of) the ndarray that | |
satisfies the requirements then a new reference is returned. | |
Otherwise, a new array is constructed. The contents of *obj* | |
are copied to the new array unless the array interface is used | |
so that data does not have to be copied. Objects that can be | |
converted to an array include: 1) any nested sequence object, | |
2) any object exposing the array interface, 3) any object with | |
an :obj:`__array__` method (which should return an ndarray), | |
and 4) any scalar object (becomes a zero-dimensional | |
array). Sub-classes of the ndarray that otherwise fit the | |
requirements will be passed through. If you want to ensure | |
a base-class ndarray, then use :cdata:`NPY_ENSUREARRAY` in the | |
requirements flag. A copy is made only if necessary. If you | |
want to guarantee a copy, then pass in :cdata:`NPY_ENSURECOPY` | |
to the requirements flag. | |
*typenum* | |
One of the enumerated types or :cdata:`NPY_NOTYPE` if the data-type | |
should be determined from the object itself. The C-based names | |
can be used: | |
:cdata:`NPY_BOOL`, :cdata:`NPY_BYTE`, :cdata:`NPY_UBYTE`, | |
:cdata:`NPY_SHORT`, :cdata:`NPY_USHORT`, :cdata:`NPY_INT`, | |
:cdata:`NPY_UINT`, :cdata:`NPY_LONG`, :cdata:`NPY_ULONG`, | |
:cdata:`NPY_LONGLONG`, :cdata:`NPY_ULONGLONG`, :cdata:`NPY_DOUBLE`, | |
:cdata:`NPY_LONGDOUBLE`, :cdata:`NPY_CFLOAT`, :cdata:`NPY_CDOUBLE`, | |
:cdata:`NPY_CLONGDOUBLE`, :cdata:`NPY_OBJECT`. | |
Alternatively, the bit-width names can be used as supported on the | |
platform. For example: | |
:cdata:`NPY_INT8`, :cdata:`NPY_INT16`, :cdata:`NPY_INT32`, | |
:cdata:`NPY_INT64`, :cdata:`NPY_UINT8`, | |
:cdata:`NPY_UINT16`, :cdata:`NPY_UINT32`, | |
:cdata:`NPY_UINT64`, :cdata:`NPY_FLOAT32`, | |
:cdata:`NPY_FLOAT64`, :cdata:`NPY_COMPLEX64`, | |
:cdata:`NPY_COMPLEX128`. | |
The object will be converted to the desired type only if it | |
can be done without losing precision. Otherwise ``NULL`` will | |
be returned and an error raised. Use :cdata:`NPY_FORCECAST` in the | |
requirements flag to override this behavior. | |
*requirements* | |
The memory model for an ndarray admits arbitrary strides in | |
each dimension to advance to the next element of the array. | |
Often, however, you need to interface with code that expects a | |
C-contiguous or a Fortran-contiguous memory layout. In | |
addition, an ndarray can be misaligned (the address of an | |
element is not at an integral multiple of the size of the | |
element) which can cause your program to crash (or at least | |
work more slowly) if you try and dereference a pointer into | |
the array data. Both of these problems can be solved by | |
converting the Python object into an array that is more | |
"well-behaved" for your specific usage. | |
The requirements flag allows specification of what kind of | |
array is acceptable. If the object passed in does not satisfy | |
this requirements then a copy is made so that thre returned | |
object will satisfy the requirements. these ndarray can use a | |
very generic pointer to memory. This flag allows specification | |
of the desired properties of the returned array object. All | |
of the flags are explained in the detailed API chapter. The | |
flags most commonly needed are :cdata:`NPY_ARRAY_IN_ARRAY`, | |
:cdata:`NPY_OUT_ARRAY`, and :cdata:`NPY_ARRAY_INOUT_ARRAY`: | |
.. cvar:: NPY_ARRAY_IN_ARRAY | |
Equivalent to :cdata:`NPY_ARRAY_C_CONTIGUOUS` \| | |
:cdata:`NPY_ARRAY_ALIGNED`. This combination of flags is useful | |
for arrays that must be in C-contiguous order and aligned. | |
These kinds of arrays are usually input arrays for some | |
algorithm. | |
.. cvar:: NPY_ARRAY_OUT_ARRAY | |
Equivalent to :cdata:`NPY_ARRAY_C_CONTIGUOUS` \| | |
:cdata:`NPY_ARRAY_ALIGNED` \| :cdata:`NPY_ARRAY_WRITEABLE`. This | |
combination of flags is useful to specify an array that is | |
in C-contiguous order, is aligned, and can be written to | |
as well. Such an array is usually returned as output | |
(although normally such output arrays are created from | |
scratch). | |
.. cvar:: NPY_ARRAY_INOUT_ARRAY | |
Equivalent to :cdata:`NPY_ARRAY_C_CONTIGUOUS` \| | |
:cdata:`NPY_ARRAY_ALIGNED` \| :cdata:`NPY_ARRAY_WRITEABLE` \| | |
:cdata:`NPY_ARRAY_UPDATEIFCOPY`. This combination of flags is | |
useful to specify an array that will be used for both | |
input and output. If a copy is needed, then when the | |
temporary is deleted (by your use of :cfunc:`Py_DECREF` at | |
the end of the interface routine), the temporary array | |
will be copied back into the original array passed in. Use | |
of the :cdata:`NPY_ARRAY_UPDATEIFCOPY` flag requires that the input | |
object is already an array (because other objects cannot | |
be automatically updated in this fashion). If an error | |
occurs use :cfunc:`PyArray_DECREF_ERR` (obj) on an array | |
with the :cdata:`NPY_ARRAY_UPDATEIFCOPY` flag set. This will | |
delete the array without causing the contents to be copied | |
back into the original array. | |
Other useful flags that can be OR'd as additional requirements are: | |
.. cvar:: NPY_ARRAY_FORCECAST | |
Cast to the desired type, even if it can't be done without losing | |
information. | |
.. cvar:: NPY_ARRAY_ENSURECOPY | |
Make sure the resulting array is a copy of the original. | |
.. cvar:: NPY_ARRAY_ENSUREARRAY | |
Make sure the resulting object is an actual ndarray and not a sub- | |
class. | |
.. note:: | |
Whether or not an array is byte-swapped is determined by the | |
data-type of the array. Native byte-order arrays are always | |
requested by :cfunc:`PyArray_FROM_OTF` and so there is no need for | |
a :cdata:`NPY_ARRAY_NOTSWAPPED` flag in the requirements argument. There | |
is also no way to get a byte-swapped array from this routine. | |
Creating a brand-new ndarray | |
---------------------------- | |
Quite often new arrays must be created from within extension-module | |
code. Perhaps an output array is needed and you don't want the caller | |
to have to supply it. Perhaps only a temporary array is needed to hold | |
an intermediate calculation. Whatever the need there are simple ways | |
to get an ndarray object of whatever data-type is needed. The most | |
general function for doing this is :cfunc:`PyArray_NewFromDescr`. All array | |
creation functions go through this heavily re-used code. Because of | |
its flexibility, it can be somewhat confusing to use. As a result, | |
simpler forms exist that are easier to use. | |
.. cfunction:: PyObject *PyArray_SimpleNew(int nd, npy_intp* dims, int typenum) | |
This function allocates new memory and places it in an ndarray | |
with *nd* dimensions whose shape is determined by the array of | |
at least *nd* items pointed to by *dims*. The memory for the | |
array is uninitialized (unless typenum is :cdata:`NPY_OBJECT` in | |
which case each element in the array is set to NULL). The | |
*typenum* argument allows specification of any of the builtin | |
data-types such as :cdata:`NPY_FLOAT` or :cdata:`NPY_LONG`. The | |
memory for the array can be set to zero if desired using | |
:cfunc:`PyArray_FILLWBYTE` (return_object, 0). | |
.. cfunction:: PyObject *PyArray_SimpleNewFromData( int nd, npy_intp* dims, int typenum, void* data) | |
Sometimes, you want to wrap memory allocated elsewhere into an | |
ndarray object for downstream use. This routine makes it | |
straightforward to do that. The first three arguments are the same | |
as in :cfunc:`PyArray_SimpleNew`, the final argument is a pointer to a | |
block of contiguous memory that the ndarray should use as it's | |
data-buffer which will be interpreted in C-style contiguous | |
fashion. A new reference to an ndarray is returned, but the | |
ndarray will not own its data. When this ndarray is deallocated, | |
the pointer will not be freed. | |
You should ensure that the provided memory is not freed while the | |
returned array is in existence. The easiest way to handle this is | |
if data comes from another reference-counted Python object. The | |
reference count on this object should be increased after the | |
pointer is passed in, and the base member of the returned ndarray | |
should point to the Python object that owns the data. Then, when | |
the ndarray is deallocated, the base-member will be DECREF'd | |
appropriately. If you want the memory to be freed as soon as the | |
ndarray is deallocated then simply set the OWNDATA flag on the | |
returned ndarray. | |
Getting at ndarray memory and accessing elements of the ndarray | |
--------------------------------------------------------------- | |
If obj is an ndarray (:ctype:`PyArrayObject *`), then the data-area of the | |
ndarray is pointed to by the void* pointer :cfunc:`PyArray_DATA` (obj) or | |
the char* pointer :cfunc:`PyArray_BYTES` (obj). Remember that (in general) | |
this data-area may not be aligned according to the data-type, it may | |
represent byte-swapped data, and/or it may not be writeable. If the | |
data area is aligned and in native byte-order, then how to get at a | |
specific element of the array is determined only by the array of | |
npy_intp variables, :cfunc:`PyArray_STRIDES` (obj). In particular, this | |
c-array of integers shows how many **bytes** must be added to the | |
current element pointer to get to the next element in each dimension. | |
For arrays less than 4-dimensions there are :cfunc:`PyArray_GETPTR{k}` | |
(obj, ...) macros where {k} is the integer 1, 2, 3, or 4 that make | |
using the array strides easier. The arguments .... represent {k} non- | |
negative integer indices into the array. For example, suppose ``E`` is | |
a 3-dimensional ndarray. A (void*) pointer to the element ``E[i,j,k]`` | |
is obtained as :cfunc:`PyArray_GETPTR3` (E, i, j, k). | |
As explained previously, C-style contiguous arrays and Fortran-style | |
contiguous arrays have particular striding patterns. Two array flags | |
(:cdata:`NPY_C_CONTIGUOUS` and :cdata`NPY_F_CONTIGUOUS`) indicate | |
whether or not the striding pattern of a particular array matches the | |
C-style contiguous or Fortran-style contiguous or neither. Whether or | |
not the striding pattern matches a standard C or Fortran one can be | |
tested Using :cfunc:`PyArray_ISCONTIGUOUS` (obj) and | |
:cfunc:`PyArray_ISFORTRAN` (obj) respectively. Most third-party | |
libraries expect contiguous arrays. But, often it is not difficult to | |
support general-purpose striding. I encourage you to use the striding | |
information in your own code whenever possible, and reserve | |
single-segment requirements for wrapping third-party code. Using the | |
striding information provided with the ndarray rather than requiring a | |
contiguous striding reduces copying that otherwise must be made. | |
Example | |
======= | |
.. index:: | |
single: extension module | |
The following example shows how you might write a wrapper that accepts | |
two input arguments (that will be converted to an array) and an output | |
argument (that must be an array). The function returns None and | |
updates the output array. | |
.. code-block:: c | |
static PyObject * | |
example_wrapper(PyObject *dummy, PyObject *args) | |
{ | |
PyObject *arg1=NULL, *arg2=NULL, *out=NULL; | |
PyObject *arr1=NULL, *arr2=NULL, *oarr=NULL; | |
if (!PyArg_ParseTuple(args, "OOO!", &arg1, &arg2, | |
&PyArray_Type, &out)) return NULL; | |
arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY); | |
if (arr1 == NULL) return NULL; | |
arr2 = PyArray_FROM_OTF(arg2, NPY_DOUBLE, NPY_IN_ARRAY); | |
if (arr2 == NULL) goto fail; | |
oarr = PyArray_FROM_OTF(out, NPY_DOUBLE, NPY_INOUT_ARRAY); | |
if (oarr == NULL) goto fail; | |
/* code that makes use of arguments */ | |
/* You will probably need at least | |
nd = PyArray_NDIM(<..>) -- number of dimensions | |
dims = PyArray_DIMS(<..>) -- npy_intp array of length nd | |
showing length in each dim. | |
dptr = (double *)PyArray_DATA(<..>) -- pointer to data. | |
If an error occurs goto fail. | |
*/ | |
Py_DECREF(arr1); | |
Py_DECREF(arr2); | |
Py_DECREF(oarr); | |
Py_INCREF(Py_None); | |
return Py_None; | |
fail: | |
Py_XDECREF(arr1); | |
Py_XDECREF(arr2); | |
PyArray_XDECREF_ERR(oarr); | |
return NULL; | |
} | |