summaryrefslogtreecommitdiff
path: root/doc/source/user/c-info.how-to-extend.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/source/user/c-info.how-to-extend.rst')
-rw-r--r--doc/source/user/c-info.how-to-extend.rst641
1 files changed, 641 insertions, 0 deletions
diff --git a/doc/source/user/c-info.how-to-extend.rst b/doc/source/user/c-info.how-to-extend.rst
new file mode 100644
index 000000000..56f3c99f1
--- /dev/null
+++ b/doc/source/user/c-info.how-to-extend.rst
@@ -0,0 +1,641 @@
+*******************
+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,
+pyrex, 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_IN_ARRAY`,
+ :cdata:`NPY_OUT_ARRAY`, and :cdata:`NPY_INOUT_ARRAY`:
+
+ .. cvar:: NPY_IN_ARRAY
+
+ Equivalent to :cdata:`NPY_CONTIGUOUS` \|
+ :cdata:`NPY_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_OUT_ARRAY
+
+ Equivalent to :cdata:`NPY_CONTIGUOUS` \|
+ :cdata:`NPY_ALIGNED` \| :cdata:`NPY_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_INOUT_ARRAY
+
+ Equivalent to :cdata:`NPY_CONTIGUOUS` \|
+ :cdata:`NPY_ALIGNED` \| :cdata:`NPY_WRITEABLE` \|
+ :cdata:`NPY_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:`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_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_FORCECAST
+
+ Cast to the desired type, even if it can't be done without losing
+ information.
+
+ .. cvar:: NPY_ENSURECOPY
+
+ Make sure the resulting array is a copy of the original.
+
+ .. cvar:: NPY_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_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:`PyArray_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:`PyArray_FLOAT` or :cdata:`PyArray_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,
+ &PyArrayType, *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;
+ }