[Matrix-SIG] Re: SWIG NumPy interfaces

Joe Van Andel vanandel@atd.ucar.edu
Mon, 12 Apr 1999 10:24:05 -0600


This is a multipart MIME message.

--==_Exmh_-12996654300
Content-Type: text/plain; charset=us-ascii

Reply-To: vanandel@ucar.edu
Cc:  pascucci <pascucci@cs.utexas.edu>
Fcc: 
--------
Here's an example of what I use.  The next release of EGCS may actually 
support templates well enough to use CXX from the LLNL distribution, 
but for now SWIG is what I use.

Joe VanAndel            Internet: vanandel@ucar.edu
National Center for     Web: http://www.atd.ucar.edu/~vanandel/home.html
Atmospheric Research



--==_Exmh_-12996654300
Content-Type: text/plain ; name="IIR_Filter.i"; charset=us-ascii
Content-Description: IIR_Filter.i

%module IIR_Filter
%{
#include "IIR_Filter.h"
#include "FloatTuple.h"
%}

%include "numpy_typemaps.i"

%typemap(python,in) float* TUPLE (float *temp) {
    int i;
    int cnt;
    if (PyTuple_Check($source)) {
    	cnt = PyTuple_Size($source);
    	temp = new float[cnt];
    	for (i=0; i < cnt; ++i) {
    	    temp[i] = PyFloat_AsDouble(PyTuple_GetItem($source, i));
    	}
    	$target = temp;
    } else {
    	 PyErr_SetString(PyExc_TypeError, "expected a tuple");	
    	 return NULL;
    }
}
%include "FloatTuple.h"





class IIR_Filter {
      public:
      	IIR_Filter(int, float, FloatTuplePtr);

    	PyObject *filter(PyArrayObject *INPUT_2D,   // I
		         PyArrayObject *INPUT_2D);   // Q
};

--==_Exmh_-12996654300
Content-Type: text/plain ; name="numpy_typemaps.i"; charset=us-ascii
Content-Description: numpy_typemaps.i

%typemap(python,in) PyArrayObject *INPUT
{
    $target = (PyArrayObject *)$source;    
}

%typemap(python,in) PyArrayObject *INPUT_1D
{
    $target = (PyArrayObject *)$source;    
    if ($target->nd != 1) {
        PyErr_SetString(PyExc_TypeError, "must be 1D array");
        return NULL;
    }
}

%typemap(python,in) PyArrayObject *INPUT_2D
{
    $target = (PyArrayObject *)$source;    
    if ($target->nd != 2) {
    //	printf("%s: num dim = %d\n", "$target", $target->nd);
        PyErr_SetString(PyExc_TypeError, "must be 2D array");
        return NULL;
    }
}

// pass 2D array of double
// by  Dr. Les Schaffer les@designspring.com

%typemap(python, in) double ** {
	 
	PyArrayObject *arr;    /* will point to our array object.      */
	PyObject ** op;        /* pointer to pointer to array object   */
                               /* cast as PyObject;                    */
			       /* (needed by PyArray_As2d).            */

	int d1, d2, type;      /* ints neeed by PyArray_As2D.          */
	char ***ptr;           /* need by PyArray_As2D.                */
                             
	double ** arrayPtr_2D; /* this is our double ** array pointer. */
                               /* C extensions can then access         */
                               /* arbitrary sized 2D arrays as         */
                               /* arrayPtr[i][j].                      */

	/* point ptr to the address of ArrayPtr_2D. */
	/* PyArray_As2D will then place in it a     */
        /* char **  pointer aimed at a set of       */
        /* pointers  to the rows of our array.      */
	ptr = (char ***) & arrayPtr_2D;

	/* here is our array object from caller	*/
	arr = (PyArrayObject *) $source;   

	/* point op at our array object pointer */
	op = (PyObject **)&arr;

	/* i use double almost always */
	type = (int) PyArray_DOUBLE;   

	/* now let PyArray_As2D re-arrange, if necessary (?),  */
	/* our array and set the pointers to the rows of array */
	PyArray_As2D( op, ptr, &d1, &d2, type); 
	
	/* done. hand arrayPtr2D to our C ext */
	$target = arrayPtr_2D; 
}


%typemap(python,out) PyObject * {
    $target = $source;
}

// grab a 12 element array from a Python tuple

%typemap(python,in) float[12] (float temp[12]){
    int i;
    if (PyTuple_Check($source)) {
    	if (!PyArg_ParseTuple($source, "ffffffffffff",
	   temp, temp+1, temp+2, temp+3,
	   temp+4, temp+5, temp+6, temp+7,
	   temp+8, temp+9, temp+10, temp+11)) {
	   PyErr_SetString(PyExc_TypeError, "tuple must have 12 elements");
	       return NULL;
										       }
	$target = &temp[0];
    } else {
    	PyErr_SetString(PyExc_TypeError, "expected a tuple");	
    	  return NULL;
    }   
}

%typemap(python,in) float[13] (float temp[13]){
    int i;
    if (PyTuple_Check($source)) {
    	if (!PyArg_ParseTuple($source, "fffffffffffff",
	   temp, temp+1, temp+2, temp+3,
	   temp+4, temp+5, temp+6, temp+7,
	   temp+8, temp+9, temp+10, temp+11,
	   temp+12 )) {
	   PyErr_SetString(PyExc_TypeError, "tuple must have 13 elements");
	       return NULL;
										       }
	$target = &temp[0];
    } else {
    	PyErr_SetString(PyExc_TypeError, "expected a tuple");	
    	  return NULL;
    }   
}

%typemap(python,in) float[15] (float temp[15]){
    int i;
    if (PyTuple_Check($source)) {
    	if (!PyArg_ParseTuple($source, "fffffffffffffff",
	   temp, temp+1, temp+2, temp+3,
	   temp+4, temp+5, temp+6, temp+7,
	   temp+8, temp+9, temp+10, temp+11,
	   temp+12, temp+13, temp+14)) {
	   PyErr_SetString(PyExc_TypeError, "tuple must have 15 elements");
	       return NULL;
										       }
	$target = &temp[0];
    } else {
    	PyErr_SetString(PyExc_TypeError, "expected a tuple");	
    	  return NULL;
    }   
}


--==_Exmh_-12996654300
Content-Type: text/plain ; name="FloatTuple.cc"; charset=us-ascii
Content-Description: FloatTuple.cc

#include <stdio.h>    // for NULL
#include "FloatTuple.h"

FloatTuple::FloatTuple(int cnt, float *tuple)
{
    values_ = tuple;    // we're inheriting this memory
    numFloats_ = cnt;
}
FloatTuple::~FloatTuple()
{
    delete values_;
    values_ = NULL;
    numFloats_= 0;
}

    




--==_Exmh_-12996654300
Content-Type: text/plain ; name="FloatTuple.h"; charset=us-ascii
Content-Description: FloatTuple.h

#ifndef FloatTupleH
#define FloatTupleH
class FloatTuple {
 public:
    FloatTuple(int cnt, float *TUPLE);
    ~FloatTuple();
    int numFloats_;
    float *values_;

    
};
typedef FloatTuple* FloatTuplePtr;

#endif
    



    

--==_Exmh_-12996654300--