Handling C-Array Arguments
==========================

Trilinos defines a number of high-level array-like objects that store
contiguous, homogenous data.  Nevertheless, there are instances when
Trilinos objects pass low-level C-arrays as input or return arguments.

SWIG does not handle this case automatically in th emanner we would
like.  However, PyTrilinos has adopted a set of interface conventions
for dealing with them and simple methods for achieving those
interfaces.

Built-in python containers, such as list, are discontiguous and
heterogeneous, which makes them unsuitable for efficiently handling
C-array type data.  Fortunately, there is a third party module named
NumPy that has been adopted by the python community for just this
purpose.  (This adoption has been hard won -- NumPy brought together
two divergent efforts named Numeric and NumArray.)  Included in the
NumPy distribution is a file named ``numpy.i``, which is a SWIG
interface file that provides typemaps and other tools.  This file has
been copied to the PyTrilinos/src directory and is used by PyTrilinos
SWIG interface files for handling C-array arguments.

To learn how to use ``numpy.i``, its `documentation is online
<http://docs.scipy.org/doc/numpy/reference/swig.interface-file.html>`_.

Code that needs to interface with NumPy should call the function
``import_array()``, but only once.  To avoid the possibility of two
unrelated python modules both calling ``import_array()`` in a
conflicting way, NumPy requires that you define a macro
``PY_ARRAY_UNIQUE_SYMBOL``.  In PyTrilinos, we do::

  #define PY_ARRAY_UNIQUE_SYMBOL PyTrilinos

However, we must also guard against two or more PyTrilinos modules
calling ``import_array()``.  To do this, we define a singleton class
``NumPyImporter`` that calls ``import_array()`` and lives in the
``pytrilinos`` shared library.  All PyTrilinos extension modules link
against this library and so the first one to be imported will
instantiate the ``NumPyImporter`` object, which calls
``import_array()`` in its constructor.

For this reason, the initialization instructions in the ``numpy.i``
instructions should be ignored, as they are for a single python module
environment.  Instead, all a PyTrilinos developer has to do is add::

  %{
  #include "numpy_include.h"
  %}
  %include "numpy.i"

to his SWIG interface file, and then start using the ``%apply``
directive as described in the ``numpy.i`` documentation.
