APPENDIX 1

Making Shadow Classes with SWIG

 

A shadow class in Python is really a Python class.  It calls various C++ functions generated by SWIG, which in turn call the original C++ functions.  A template class such as mac::vector3D<T> needs to be slightly modified before using SWIG.  This appendix shows some examples on how to modify the original C++ code and to instruct SWIG by writing the interface file.

 

A1.1 Modifying the Source Code

 

As described above, the first step is to copy the source code in C++ to another place, and make necessary changes.  It is still hard to write the C++ code directly compatible with SWIG.  These changes include the following.

 

Nested class

Nested class definition must be removed or commented out before using SWIG, since it is not supported.

 

Overloading

The order of overloaded functions and operators may be sorted such that the one will appear in Python is the first one.  The later ones will be ignored.  If they are not sorted, explicit instruction is needed in the interface file in order to ignore some overloaded functions and operators.  If overloaded functions and operators are desired in Python, some of them must be renamed in the interface file.  See below for more.

 

Non-member functions

Unbounded non-member functions should be removed.  If they are really needed, they should reside in a separate function module.  I have not found a way to merge functions with classes in one module.

 

Additional member functions

Additional member functions specific to Python shadow class may be included, such as __str__, __repr__, etc.

 

Others

It may be desirable to merge the .c++ file into the header file, but if the .c++ file is too long, it can be included at the end of the header file by using #include, and still kept as a separate file.  Other unnecessary bits can be removed in order to make the SWIG interface file and output log cleaner.

 

The following listing is the modified vector3D.h.

 

#ifndef CPL_MAC_VECTOR3D_H

#define CPL_MAC_VECTOR3D_H

 

#include <iostream.h>

#include <strstream.h>

#include <fstream.h>

#include <algo.h>

#include <complex.h>

#include <float.h>

#include "utility.h"

#include "matrix3D.h"

 

namespace mac

{

 

template <class T>

class vector3D

{

      friend ostream &operator<<(ostream& out, const vector3D<T>& v)

         {out << v.getX() << "," << v.getY() << "," << v.getZ();

          return out;}

 

   public:

      vector3D(const T u = 0, const T v = 0, const T w = 0)

         : x(u), y(v), z(w) {}

      vector3D(const vector3D<T>& v) : x(v.x), y(v.y), z(v.z) {}

     ~vector3D() {}

 

   // Conversion

   // operator vector3() const {return vector3(x, y, z);}

//    operator vector3D<double>() const {return vector3D<double>(x, y, z);}

//    operator vector3D<int>   () const

//       {return vector3D<int>(int(x), int(y), int(z));}

      vector3D<int> nearest() const

         {return vector3D<int>(mac::nearest(x),

                               mac::nearest(y),

                               mac::nearest(z));}

 

   // Output

//    void write(ofstream* f) const {if (f) *f << *this << endl;}

   // void write(const char* = message::typeGeneral) const;

#ifdef SWIG

      %extend

         {char *__str__()

            {ostrstream line;

             line << "<" << self->getX() << " "

                         << self->getY() << " "

                         << self->getZ() << ">" << ends;

             return line.str();}}

#endif

 

   // Element access

      inline T  operator()(const int i) const

         {switch (i) {case 1: return x; case 2: return y; case 3: return z;

                      default: assert (0);}

          return x;} // This will never happen.

      inline T& operator()(const int i) // 1-offset, i = 1 - 3

         {switch (i) {case 1: return x; case 2: return y; case 3: return z;

                      default: assert (0);}

          return x;} // This will never happen.

      inline T  operator[](const int i) const {return (*this)(i + 1);}

         // 0-offset, i = 0 - 2

      inline T& operator[](const int i)       {return (*this)(i + 1);}

      T getX() const {return x;}

      T getY() const {return y;}

      T getZ() const {return z;}

 

   // Assignment

      const vector3D<T> &operator=(const vector3D<T>& v)

         {if (&v != this) {x = v.x; y = v.y; z = v.z;} return *this;}

 

   // Addition/subtraction

      vector3D<T> operator+=(const vector3D<T>& v)

         {x += v.x; y += v.y; z += v.z; return *this;}

      vector3D<T> operator-=(const vector3D<T>& v)

         {x -= v.x; y -= v.y; z -= v.z; return *this;}

      vector3D<T> operator+(const vector3D<T>& v) const

         {vector3D<T> u = *this; return u += v;}

      vector3D<T> operator-(const vector3D<T>& v) const

         {vector3D<T> u = *this; return u -= v;}

      vector3D<T> operator+() const {return *this;}

      vector3D<T> operator-() const {return vector3D<T>(0, 0, 0) - *this;}

 

   // Pre-multiplication

      vector3D<T> operator*=(const mac::matrix3D<T>& m)

         {vector3D<T> v = *this;

          x = m(1, 1) * v.x + m(1, 2) * v.y + m(1, 3) * v.z;

          y = m(2, 1) * v.x + m(2, 2) * v.y + m(2, 3) * v.z;

          z = m(3, 1) * v.x + m(3, 2) * v.y + m(3, 3) * v.z;

          return *this;}

      vector3D<T> operator/=(const mac::matrix3D<T>& m)

         {mac::matrix3D<T> n = m; n.inverse(); return *this *= n;}

      vector3D<T> operator*(const mac::matrix3D<T>& m) const

         // Caution: This operator means matrix3D<T> * vector3D<T>, returns a

         //          vector3D<T>.

         {vector3D<T> v = *this; return v *= m;}

 

   // Scaling

      vector3D<T> operator*=(const T a)          //   isotropic scaling

         {x *= a; y *= a; z *= a; return *this;}

      vector3D<T> operator/=(const T a)          //   isotropic scaling

         {x /= a; y /= a; z /= a; return *this;}

      vector3D<T> operator*=(const vector3D<T>& v)

         {x *= v.x; y *= v.y; z *= v.z; return *this;}   // anisotropic scaling

      vector3D<T> operator/=(const vector3D<T>& v)

         {assert (v.x && v.y && v.z);

          x /= v.x; y /= v.y; z /= v.z;

          return *this;}                                 // anisotropic scaling

      vector3D<T> operator*(const T a)         const    //   isotropic scaling

         {vector3D<T> v = *this; return v *= a;}

      vector3D<T> operator/(const T a)         const    //   isotropic scaling

         {vector3D<T> v = *this; return v /= a;}

      vector3D<T> operator/(const vector3D<T>& v) const  // anisotropic scaling

         {vector3D<T> u = *this; return u /= v;}

 

   // Cross (vector) multiplication

      static vector3D<T> cross(const vector3D<T>& u, const vector3D<T>& v)

         {return vector3D<T>(u.y * v.z - u.z * v.y,

                             u.z * v.x - u.x * v.z,

                             u.x * v.y - u.y * v.x);}

      vector3D<T> cross(const vector3D<T> &v) const {return cross(*this, v);}

      vector3D<T> operator->*(const vector3D<T> &v) const {return cross(v);}

 

   // Dot (scalar) multiplication

      static T dot(const vector3D<T> &u, const vector3D<T> &v)

         {return u.x * v.x + u.y * v.y + u.z * v.z;}

      T dot(const vector3D<T> &v) const {return dot(*this, v);}

      T operator*(const vector3D<T> &v) const {return dot(v);}

 

   // Length

      static double vabs(const T x, const T y, const T z)

         {return sqrt(double(x * x + y * y + z * z));}

      static double vabs(const vector3D<T> &v) {return vabs(v.x, v.y, v.z);}

      double vabs() const {return vabs(*this);}

 

      static T vnorm(const T x, const T y, const T z)

         {return vnorm(vector3D<T>(x, y, z));}

      static T vnorm(const vector3D<T> &v)

         {return v.x * v.x + v.y * v.y + v.z * v.z;}

      T vnorm() const {return vnorm(*this);}

 

      static bool shorterThan(const vector3D<T>& u, const vector3D<T>& v)

         {const T un = u.vnorm();

          const T vn = v.vnorm();

          if (un == vn) return u  < v;

          else          return un < vn;}

      bool shorterThan(const vector3D<T> &v) const

         {return shorterThan(*this, v);}

 

   // class shorter

   // {

   //    public:

   //       bool operator()(const vector3D<T>& u, const vector3D<T>& v) const

   //          {return shorterThan(u, v);}

   // };

 

   // Comparison

      bool operator!() const {return *this == vector3D<T>(0, 0, 0);}

      bool operator==(const vector3D<T> &v) const

          {return x == v.getX() && y == v.getY() && z == v.getZ();}

      bool operator!=(const vector3D<T> &v) const

          {return x != v.getX() || y != v.getY() || z != v.getZ();}

      bool operator&=(const vector3D<T> &v) const // approximately equal

          {return vnorm(*this - v) < 10 * FLT_EPSILON;}

      bool operator> (const vector3D<T> &v) const

         {return !(*this < v) && !(*this == v);}

      bool operator< (const vector3D<T> &v) const

         {return lessThan(*this, v);}

      bool operator>=(const vector3D<T> &v) const

         {return *this > v || *this == v;}

      bool operator<=(const vector3D<T> &v) const

         {return *this < v || *this == v;}

 

      static bool lessThan(const vector3D<T>& u, const vector3D<T>& v)

         {if (u.x == v.x)

             if (u.y == v.y) return u.z < v.z;

             else            return u.y < v.y;

          else               return u.x < v.x;}

 

//    class less

//    {

//       public:

//          bool operator()(const vector3D<T>& u, const vector3D<T>& v) const

//             {return lessThan(u, v);}

//    };

 

   // Projection

      double projectionOn(const vector3D<T>& v) const

         {assert (!!v); return dot(v) / v.vabs();}

         // Projection of *this on v.

      complex<double> projectionOn(const vector3D<T>& u, const vector3D<T>& v)

         const {return complex<double>(projectionOn(u), projectionOn(v));}

         // Projection of *this on u and v.

      vector3D<double> projectionOn(const vector3D<T>& u,

                                    const vector3D<T>& v,

                                    const vector3D<T>& w) const

         {return vector3D<double>(projectionOn(u),

                                  projectionOn(v),

                                  projectionOn(w));}

         // Projection of *this on u, v, and w.

      double projectionOf(const vector3D<T>& v) const

         {assert (!!*this); return dot(v) / vabs();}

         // Projection of v on *this.

      static double projection(const vector3D<T>& u, const vector3D<T>& v)

         {assert (!!v); return u * v / v.vabs();} // Projection of u on v.

      static T projectionSq(const vector3D<T>& u, const vector3D<T>& v)

         {assert (!!v);

          const T d = u * v;

          const T p = d * d / v.vnorm();

          return d >= 0 ? p : -p;}

         // The squared projection of u on v.  Do not use with T being any

         // integer type.

 

   // Orientation

      vector3D<double> vcos() const

         {assert (!!*this); const double r = vabs();

          return r ? vector3D<double>(x, y, z) / r : vector3D<double>(0, 0, 0);}

          //return r ? *this / r : vector3D<double>(0, 0, 0);}

      vector3D<double> vsin() const

         {const vector3D<double> a = orientationAngle();

          return vector3D<double>(sin(a.getX()),

                                  sin(a.getY()),

                                  sin(a.getZ()));}

      vector3D<double> vtan() const

         {const vector3D<double> a = orientationAngle();

          return vector3D<double>(tan(a.getX()),

                                  tan(a.getY()),

                                  tan(a.getZ()));}

      vector3D<double> orientationAngle() const

         {const vector3D<double> c = vcos();

          return vector3D<double>(acos(c.getX()),

                                  acos(c.getY()),

                                  acos(c.getZ()));}

      complex<double> polarAngle() const

         // Polar angles psi and phi define an orientation.  In a orthogonal

         // coordinate system, rotating Y-axis around Z-axis by psi according

         // to the left-hand rule, followed by a rotation of the new Y-axis

         // around the old Y-axis by phi according to the right-hand rule, the

         // resulting Y-axis is the orientation defined by polar angles psi

         // and phi (Z. Ren, Thesis, Academia Sinica, Beijing, China, 1990).

         {const vector3D<double> c = vcos();

          const double psi = acos(c.getY());

                      // 0 <= psi <= pi, therefore sin(psi) >= 0.

          double phi; // 0 <= phi <= pi, so the return phi is (-pi, pi].

          const double sinPsi = sin(psi);

          if (!sinPsi) phi = 0;

          else {const double cosPhi = c.getX() / sinPsi;

                if      (cosPhi >=  1) phi = 0;

                else if (cosPhi <= -1) phi = M_PI;

                else                   phi = acos(cosPhi);}

          return c.getZ() > 0 ? complex<double>(psi, -phi) :

                           complex<double>(psi,  phi);}

      vector3D<double> polarAngle(const double kappa) const

         {const complex<double> polar = polarAngle();

          return vector3D<double>(real(polar), imag(polar), kappa);}

      bool operator||(const vector3D<T> &v) const

         {return this->vcos() == v.vcos() && !!v;}

      bool parallel(const vector3D<T> &v) const {return *this || v;}

      bool antiparallel(const vector3D<T> &v) const {return *this || -v;}

      bool perpendicular(const vector3D<T> &v) const {return !(*this * v);}

 

   // Distance

      static double distance(const vector3D<T> &u, const vector3D<T> &v)

         {return vabs(u.x - v.x, u.y - v.y, u.z - v.z);}

      double distance(const vector3D<T> &v) const {return distance(*this, v);}

      double operator|(const vector3D<T> &v) const {return distance(v);}

 

   // Angle

      static double cosAngle(const vector3D<T> &u, const vector3D<T> &v)

         {return (u * v) / (vabs(u) * vabs(v));}

      double cosAngle(const vector3D<T> &v) const {return cosAngle(*this, v);}

      static double sinAngle(const vector3D<T> &u, const vector3D<T> &v)

         {return vabs(u ->* v) / (vabs(u) * vabs(v));}

      double sinAngle(const vector3D<T> &v) const {return sinAngle(*this, v);}

      static double tanAngle(const vector3D<T> &u, const vector3D<T> &v)

         {return vabs(u ->* v) / (u * v);}

      double tanAngle(const vector3D<T> &v) const {return tanAngle(*this, v);}

      static double angle(const vector3D<T> &u, const vector3D<T> &v)

         // in radian

         {return atan2(sinAngle(u, v), cosAngle(u, v));}

      double angle(const vector3D<T> &v) const {return angle(*this, v);}

      double operator^(const vector3D<T> &v) const {return angle(v);}

 

   // Area

      static double triangleVertices(const vector3D<T> &u,

                                     const vector3D<T> &v,

                                     const vector3D<T> &w)

         // u, v, w are vertices

         {return vabs((v - u) ->* (w - u)) / 2;}

      double triangleVertices(const vector3D<T> &u, const vector3D<T> &v) const

         {return triangleVertices(*this, u, v);}

 

      static double triangleEdges(const vector3D<T> &u,

                                     const vector3D<T> &v)

         // u and v are two edges

         {return triangleVertices(vector3D<T>(0, 0, 0), u, v);}

      double triangleEdges(const vector3D<T> &v) const

         {return triangleEdges(*this, v);}

 

   // Volume

      static T scalarTripleProduct(const vector3D<T> &u,

                                   const vector3D<T> &v,

                                   const vector3D<T> &w)

         {return u * (v ->* w);}

      T scalarTripleProduct(const vector3D<T> &u, const vector3D<T> &v) const

         {return scalarTripleProduct(*this, u, v);}

 

      static T parallelepipedVolume(const vector3D<T> &u,

                                    const vector3D<T> &v,

                                    const vector3D<T> &w)

         {const T stp = scalarTripleProduct(u, v, w);

          return stp < 0 ? -stp : stp;}

      T parallelepipedVolume(const vector3D<T> &u, const vector3D<T> &v) const

         {return parallelepipedVolume(*this, u, v);}

 

   // Location

      bool  inside(const vector3D<T> &u, const vector3D<T> &v) const

         // Return whether *this is inside the parallelepiped whose two body

         // diagonal vertices are u and v, respectively.

         {return min(u.x, v.x) <= x && x <= max(u.x, v.x) &&

                 min(u.y, v.y) <= y && y <= max(u.y, v.y) &&

                 min(u.z, v.z) <= z && z <= max(u.z, v.z);}

      bool outside(const vector3D<T> &u, const vector3D<T> &v) const

         {return !inside(u, v);}

 

   private:

      T x, y, z;

};

 

} // namespace mac

 

/*

template <class T>

mac::vector3D<double> sin(const mac::vector3D<T>& v) {return v.vsin();}

template <class T>

mac::vector3D<double> cos(const mac::vector3D<T>& v) {return v.vcos();}

template <class T>

mac::vector3D<double> tan(const mac::vector3D<T>& v) {return v.vtan();}

template <class T>

double   abs(const mac::vector3D<T>& v) {return v.vabs();}

template <class T>

double   abs(const T& x, const T& y, const T& z)

   {return mac::vector3D<T>(x, y, z).vabs();}

template <class T>

double  norm(const mac::vector3D<T>& v) {return v.vnorm();}

template <class T>

double  norm(const T& x, const T& y, const T& z)

   {return mac::vector3D<T>(x, y, z).vnorm();}

template <class T>

double  vabs(const mac::vector3D<T>& v) {return v.vabs();}

template <class T>

T      vnorm(const mac::vector3D<T>& v) {return v.vnorm();}

template <class T>

double  vabs(const T& x, const T& y, const T& z)

   {return mac::vector3D<T>(x, y, z).vabs();}

template <class T>

T      vnorm(const T& x, const T& y, const T& z)

   {return mac::vector3D<T>(x, y, z).vnorm();}

template <class T>

T   dot_prod(const mac::vector3D<T>& v1,

             const mac::vector3D<T>& v2) {return v1 * v2;}

template <class T>

mac::vector3D<T> operator*(const T& x,

                           const mac::vector3D<T>& v) {return v * x;}

template <class T>

mac::vector3D<T> operator/(const T& x, const mac::vector3D<T>& v)

   {return mac::vector3D<T>(x, x, x) / v;}

template <class T>

mac::vector3D<T> operator*(const mac::matrix3D<T>& m,

                           const mac::vector3D<T>& v)

   {return v * m;} // pre-multiplication

*/

 

#endif

 

Listing A1.1.0.0.1 The modified vector3D.h ready for wrapping by SWIG.

 

Several shadow classes can be included in a module.  Listing A1.1.0.0.2 shows matrix3D.h.  This header file includes the .c++ file at the end.

 

#ifndef CPL_MAC_MATRIX3D_H

#define CPL_MAC_MATRIX3D_H

 

#include <iostream.h>

#include <strstream.h>

#include <assert.h>

//#include "matrix.h"

 

namespace mac

{

 

template <class T> class vector3D;

 

template <class T>

class matrix3D

{

      friend ostream &operator<<(ostream& out, const matrix3D<T>& m)

         {out << m.r11 << "," << m.r12 << "," << m.r13 << "\n"

              << m.r21 << "," << m.r22 << "," << m.r23 << "\n"

              << m.r31 << "," << m.r32 << "," << m.r33;

          return out;}

      friend class polarRotationMatrix;

      friend class polarToPolarRotationMatrix;

      friend class EulerRotationMatrix;

 

   public:

      matrix3D(const T a11 = 1, const T a12 = 0, const T a13 = 0,

               const T a21 = 0, const T a22 = 1, const T a23 = 0,

               const T a31 = 0, const T a32 = 0, const T a33 = 1)

         : r11(a11), r12(a12), r13(a13),

           r21(a21), r22(a22), r23(a23),

           r31(a31), r32(a32), r33(a33) {}

      matrix3D(const matrix3D<T>& m)

         : r11(m.r11), r12(m.r12), r13(m.r13),

           r21(m.r21), r22(m.r22), r23(m.r23),

           r31(m.r31), r32(m.r32), r33(m.r33) {}

     ~matrix3D() {}

 

   // Conversion operators

   // operator matrix() const

   //    {return matrix(r11, r12, r13, r21, r22, r23, r31, r32, r33);}

      operator matrix3D<double>() const;

 

   // Output

#ifdef SWIG

      %extend

         {char *__str__()

            {ostrstream line;

             line << " /" << (*self)(1, 1) << " "

                          << (*self)(1, 2) << " "

                          << (*self)(1, 3) << endl

                  << "< " << (*self)(2, 1) << " "

                          << (*self)(2, 2) << " "

                          << (*self)(2, 3) << endl

                  << " \\"<< (*self)(3, 1) << " "

                          << (*self)(3, 2) << " "

                          << (*self)(3, 3) << ends;

             return line.str();}}

#endif

 

   // Element access

      T  operator()(const int, const int) const; // 1 - 3, 1-offset

      T& operator()(const int, const int);

      mac::vector3D<T> operator()(const int i) const  // 1 - 3, 1-offset

         {return (*this)[i - 1];}

      mac::vector3D<T> operator[](const int i) const  // 0 - 2, 0-offset

         {return mac::vector3D<T>((*this)(i + 1, 1),

                                  (*this)(i + 1, 2),

                                  (*this)(i + 1, 3));}

 

   // Assignment

      const matrix3D<T> &operator=(const matrix3D<T>&);

 

   // Comparison

      bool operator==(const matrix3D<T>&) const;

      bool operator&=(const matrix3D<T>&) const; // Approximately equal

      bool operator!=(const matrix3D<T>& m) const {return !(*this == m);}

      bool operator> (const matrix3D<T> &m) const

         {return *this != m && !(*this < m);}

      bool operator< (const matrix3D<T> &m) const;

      bool operator>=(const matrix3D<T> &m) const

         {return *this > m || *this == m;}

      bool operator<=(const matrix3D<T> &m) const

         {return *this < m || *this == m;}

 

   // Addition and subtraction

      matrix3D<T> operator+=(const matrix3D<T>&);

      matrix3D<T> operator-=(const matrix3D<T>&);

      matrix3D<T> operator+(const matrix3D<T>& m) const

         {matrix3D<T> n = *this; return n += m;}

      matrix3D<T> operator-(const matrix3D<T>& m) const

         {matrix3D<T> n = *this; return n -= m;}

      matrix3D<T> operator+() const {return *this;}

      matrix3D<T> operator-() const

         {return matrix3D<T>(T(0), T(0), T(0),

                             T(0), T(0), T(0),

                             T(0), T(0), T(0)) - *this;}

 

   // Scaling or multiplication by a value

      matrix3D<T> operator*=(const T);

      matrix3D<T> operator/=(const T);

      matrix3D<T> operator*(const T a) const

         {matrix3D<T> m = *this; return m *= a;}

      matrix3D<double> operator/(const T a) const

         {assert (a); matrix3D<double> m = *this; return m /= double(a);}

 

   // Multiplication by a matrix

      matrix3D<T> operator*=(const matrix3D<T>& m) // pre-multiplication

         {return *this = m * *this;}

      matrix3D<T> operator/=(const matrix3D<T> &m)

         {matrix3D<T> n = m; return *this = n.inverse() * *this;}

         // A /= B means A = ~B * A

      matrix3D<T> operator*(const matrix3D<T>&)   const;

      matrix3D<double> operator/(const matrix3D<T>& m) const // A / B = ~B * A

         {return ~m * matrix3D<double>(*this);}

 

   // Pre-multiplication to a vector

      mac::vector3D<T> operator*(const mac::vector3D<T>& v) const

         // pre-multiplication

         {return v * *this;}

 

   // Determinant

      T mabs() const;

      T det() const {return this->mabs();}

      bool operator!() const {return !mabs();}

      T sub(const int, const int) const;

 

   // Transpose

      static matrix3D<T> transpose(const matrix3D<T>&);

         // The original remains.

      matrix3D<T> transpose() {return *this = transpose(*this);}

         // The original transposed.

      matrix3D<T> operator*() const {return transpose(*this);}

         // The original remains.

      bool     symmetric() const {return **this ==  *this;}

      bool antisymmetric() const {return **this == -*this;}

      bool orthogonal() const

         {return (**this *  *this &= matrix3D<T>()) &&

                 ( *this * **this &= matrix3D<T>());}

 

   // Inversion

      static matrix3D<double> inverse(const matrix3D<T>&);

         // The original remains.

      matrix3D<T> inverse();

         // The original inversed.

      matrix3D<double> operator~() const {return inverse(*this);}

         // The original remains.

 

   private:

      T r11, r12, r13,

        r21, r22, r23,

        r31, r32, r33;

};

 

} // namespace mac

 

/*

template <class T>

mac::matrix3D<T> operator*(const T& x,

                           const mac::matrix3D<T>& r) {return r * x;}

template <class T>

T  abs(const mac::matrix3D<T>& m) {return m.mabs();}

template <class T>

T mabs(const mac::matrix3D<T>& m) {return m.mabs();}

*/

 

#include "matrix3D.c++"

 

#endif

 

Listing A1.1.0.0.2 The modified header file matrix3D.h ready for SWIG.

 

A1.2 SWIG Interface File

 

The second step is to make a SWIG interface file (Listing A1.2.0.0.1), which includes the instructions for renaming or ignoring overloaded functions and operators, naming the template classes, etc.

 

%module vm

 

%{

#include <mac/vector3D.h>

#include <mac/matrix3D.h>

#include <mac/rotationMatrix.h>

%}

 

%typemap(out) complex<double>

{

   $result = PyComplex_FromDoubles($1.real(), $1.imag());

}

 

%typemap(in) complex<double>

{

   $1 = complex<double>(PyComplex_RealAsDouble($input),

                        PyComplex_ImagAsDouble($input));

}

 

%ignore                operator=;

%ignore                operator[];

%ignore                mac::vector3D::operator()(const int);

%ignore                mac::vector3D::operator*(const T) const;

%ignore                mac::vector3D::operator/(const T) const;

%ignore                mac::vector3D::operator*=(const mac::matrix3D<T>&);

%ignore                mac::vector3D::operator*=(const vector3D<T>&);

%ignore                mac::vector3D::operator/=(const mac::matrix3D<T>&);

%ignore                mac::vector3D::operator/=(const vector3D<T>&);

%rename(cross_mul)     mac::vector3D::cross(const vector3D<T>&,

                                            const vector3D<T>&);

%rename(__pow__)       mac::vector3D::operator->*(const vector3D<T>&) const;

%rename(dot_mul)       mac::vector3D::dot(const vector3D<T>&,

                                          const vector3D<T>&);

%rename(pre_mul)       mac::vector3D::operator*(const mac::matrix3D<T>&) const;

%rename(__abs__)       mac::vector3D::vabs() const;

%rename(abs_xyz)       mac::vector3D::vabs(const T, const T, const T);

%rename(abs)           mac::vector3D::vabs(const vector3D<T>&);

%rename(norm)          mac::vector3D::vnorm() const;

%rename(norm_xyz)      mac::vector3D::vnorm(const T, const T, const T);

%rename(norm_v)        mac::vector3D::vnorm(const vector3D<T>&);

%rename(shorter)       mac::vector3D::shorterThan(const vector3D<T>&,

                                                  const vector3D<T>&);

%rename(__lshift__)    mac::vector3D::shorterThan(const vector3D<T>&) const;

%rename(dist)          mac::vector3D::distance(const vector3D<T>&,

                                               const vector3D<T>&);

%ignore                mac::vector3D::operator|(const vector3D<T>&) const;

%ignore                mac::vector3D::projectionOn(const vector3D<T>&,

                                                   const vector3D<T>&) const;

%ignore                mac::vector3D::projectionOn(const vector3D<T>&,

                                                   const vector3D<T>&,

                                                   const vector3D<T>&) const;

%rename(cos)           mac::vector3D::vcos() const;

%rename(sin)           mac::vector3D::vsin() const;

%rename(tan)           mac::vector3D::vtan() const;

%rename(polarRotation) mac::vector3D::polarAngle(const double) const;

%rename(is_zero)       mac::vector3D::operator!() const;

%rename(__or__)        mac::vector3D::operator||(const vector3D<T>&) const;

%rename(cos_ang)       mac::vector3D::cosAngle(const vector3D<T>&,

                                               const vector3D<T>&);

%rename(sin_ang)       mac::vector3D::sinAngle(const vector3D<T>&,

                                               const vector3D<T>&);

%rename(tan_ang)       mac::vector3D::tanAngle(const vector3D<T>&,

                                               const vector3D<T>&);

%rename(ang)           mac::vector3D::angle(const vector3D<T>&,

                                            const vector3D<T>&);

%rename(ap_eq)         mac::vector3D::operator&=(const vector3D<T>&) const;

%rename(triangle_vertices) mac::vector3D::triangleVertices(const vector3D<T>&,

                                                           const vector3D<T>&,

                                                           const vector3D<T>&);

%rename(triangle_edges) mac::vector3D::triangleEdges(const vector3D<T>&,

                                                     const vector3D<T>&);

%rename(scalar_triple_product) mac::vector3D::scalarTripleProduct(

                                  const vector3D<T>&,

                                  const vector3D<T>&,

                                  const vector3D<T>&);

%rename(parallelepiped_volume) mac::vector3D::parallelepipedVolume(

                                  const vector3D<T>&,

                                  const vector3D<T>&,

                                  const vector3D<T>&);

 

%rename(row)     mac::matrix3D::operator()(const int) const;

%ignore          mac::matrix3D::operator()(const int, const int);

%ignore          mac::matrix3D::operator matrix3D<double>() const;

%ignore          mac::matrix3D::operator*(const T) const;

%ignore          mac::matrix3D::operator/(const T) const;

%ignore          mac::matrix3D::operator*=(const matrix3D<T>&);

%ignore          mac::matrix3D::operator/=(const matrix3D<T>&);

%rename(__mod__) mac::matrix3D::operator*(const mac::vector3D<T>&) const;

%rename(__abs__) mac::matrix3D::mabs() const;

%rename(is_zero) mac::matrix3D::operator!() const;

%rename(trans)   mac::matrix3D::transpose(const matrix3D<T>&);

%rename(inv)     mac::matrix3D::inverse(const matrix3D<T>&);

%ignore          mac::matrix3D::operator*() const;

%rename(ap_eq)   mac::matrix3D::operator&=(const matrix3D<T>&) const;

%rename(ap_eq)   mac::vector3D::operator&=(const vector3D<T>&) const;

 

%rename(copy_polarRotationMatrix)

   mac::polarRotationMatrix::polarRotationMatrix(const mac::matrix3D<double>&);

%ignore mac::polarRotationMatrix::polarRotationMatrix(

                const complex<double>, const double);

%ignore mac::polarRotationMatrix::polarRotationMatrix(

                const mac::vector3D<double>);

%ignore mac::polarRotationMatrix::polarRotationMatrix(

                const mac::vector3D<double>, const double);

%ignore mac::polarRotationMatrix::polarRotationMatrix(const int, const double);

%ignore mac::polarRotationMatrix::set(

                const double, const double, const double,

                const double, const double, const double,

                const double, const double, const double);

 

%rename(copy_polarToPolarRotationMatrix)

   mac::polarToPolarRotationMatrix::polarToPolarRotationMatrix(

   const mac::matrix3D<double>&);

%ignore mac::polarToPolarRotationMatrix::polarToPolarRotationMatrix(

                const mac::vector3D<double>, const mac::vector3D<double>);

%ignore mac::polarToPolarRotationMatrix::polarToPolarRotationMatrix(

                const complex<double>, const mac::vector3D<double>);

%ignore mac::polarToPolarRotationMatrix::polarToPolarRotationMatrix(

                const mac::vector3D<double>, const complex<double>);

 

%rename(copy_EulerRotationMatrix)

   mac::EulerRotationMatrix::EulerRotationMatrix(const mac::matrix3D<double>&);

%ignore mac::EulerRotationMatrix::EulerRotationMatrix(

   const mac::vector3D<double>);

%ignore mac::EulerRotationMatrix::derivative(const int, const int) const;

 

%include <mac/vector3D.h>

%include <mac/matrix3D.h>

 

%template(vectorDBL) mac::vector3D<double>;

%template(vectorFLT) mac::vector3D<float>;

%template(vectorLIN) mac::vector3D<long int>;

%template(vectorINT) mac::vector3D<int>;

%template(vectorSIN) mac::vector3D<short int>;

%template(vectorLUI) mac::vector3D<long unsigned int>;

%template(vectorUIN) mac::vector3D<unsigned int>;

%template(vectorSUI) mac::vector3D<short unsigned int>;

 

%template(matrixDBL) mac::matrix3D<double>;

%template(matrixFLT) mac::matrix3D<float>;

%template(matrixLIN) mac::matrix3D<long int>;

%template(matrixINT) mac::matrix3D<int>;

%template(matrixSIN) mac::matrix3D<short int>;

%template(matrixLUI) mac::matrix3D<long unsigned int>;

%template(matrixUIN) mac::matrix3D<unsigned int>;

%template(matrixSUI) mac::matrix3D<short unsigned int>;

 

%include <mac/rotationMatrix.h>

 

Listing A1.2.0.0.1 The SWIG interface file for wrapping mac::vector3D<T>, mac::matrix3D<T>, and various rotation matrices.

 

A1.3 Running SWIG

 

Step 3, run SWIG using the command:

 

swig ¨Cc++ -c -python ¨Cshadow ¨CI/home/renz/code/cpl

   ¨Co vm_wrap.c++ vm.i

 

where, vm is the name of the new Python module.  There will be some warning messages about overloaded declarations, if nothing else is wrong.  This command generates two files of code vm.py and vm_wrap.c++.  The former defines the shadow class in Python, and the latter defines a C++ module that wraps the original C++ code.

 

The last step is to compile the generated object_wrap.c++ and the original .c++ code if any.  In this example, I have put all definitions into the header.  Then link all .o files into a shared library called vmcmodule.so.  The makefile is listed below.  Module vm is now ready.

 

SWIG = swig

CC   = g++

#CC   = /usr/local/gcc-3.0.4/bin/g++

PY   = /usr/include/python2.2

 

# define TUIHEADER TUISRC  TUIOBJ

#        MATHEADER MATHOBJ MATHSRC

BASE      = /home/renz/code

#BASE      = /home/mcsg

CPLDIR    = $(BASE)/cpl

TUIDIR    = $(BASE)/tui

MATHDIR   = $(BASE)/math

include $(TUIDIR)/makefile.classes

include $(MATHDIR)/makefile.classes

SOURCE    = $(TUIHEADER) $(TUISRC) $(MATHEADER) $(MATHSRC)

 

OPTIMIZER = -O3

DEBUG     = -ggdb -Wall -efence

INCLUDEPY = -I$(PY) -I$(PY)/Include -I$(PY)/config

INCLUDE   = -I$(TUIDIR) -I$(MATHDIR) $(INCLUDEPY)

INCLUDE_H = -I$(TUIDIR)/header -I$(MATHDIR)/header

LINK      = -lfftw -llapack -lblas -lg2c -lm

 

UTILITY   = utility

FUNCTION  = function

OBJECT    = vm

 

all: $(UTILITY).so $(FUNCTION).so $(OBJECT)cmodule.so

 

$(UTILITY).so: $(UTILITY)_wrap.o

       $(CC) -shared $? -lswigpy -o $@ $(LINK)

       echo Shared object $(UTILITY).so is made.

       echo

 

$(UTILITY)_wrap.o: $(UTILITY)_wrap.c++

       $(CC) -c $? $(OPTIMIZER) -fPIC -DHAVE_CONFIG_H $(INCLUDE)

       echo Wrapper $(UTILITY)_wrap.c++ is compiled.

       echo

 

#$(UTILITY).o: $(UTILITY).c++ $(UTILITY).h $(SOURCE)

#      $(CC) -c $< $(OPTIMIZER) -fPIC -DHAVE_CONFIG_H $(INCLUDE)

#      echo $(UTILITY).c++ is compiled.

#      echo

 

$(UTILITY)_wrap.c++: $(UTILITY).i $(UTILITY).h $(UTILITY).c++ $(SOURCE)

       $(SWIG) -c++ -c -python $(INCLUDE) -o $@ $(UTILITY).i

       echo Wrapper $(UTILITY)_wrap.c++ is generated.

       echo

 

$(FUNCTION).so: $(FUNCTION)_wrap.o $(FUNCTION).o

       $(CC) -shared $? -lswigpy -o $@ $(LINK)

       echo Shared object $(FUNCTION).so is made.

       echo

 

$(FUNCTION)_wrap.o: $(FUNCTION)_wrap.c++

       $(CC) -c $? $(OPTIMIZER) -fPIC -DHAVE_CONFIG_H $(INCLUDE)

       echo Wrapper $(FUNCTION)_wrap.c++ is compiled.

       echo

 

$(FUNCTION).o: $(FUNCTION).c++ $(FUNCTION).h $(SOURCE)

       $(CC) -c $< $(OPTIMIZER) -fPIC -DHAVE_CONFIG_H $(INCLUDE)

       echo $(FUNCTION).c++ is compiled.

       echo

 

$(FUNCTION)_wrap.c++: $(FUNCTION).i $(FUNCTION).h $(FUNCTION).c++ $(SOURCE)

       $(SWIG) -c++ -c -python $(INCLUDE) -o $@ $(FUNCTION).i

       echo Wrapper $(FUNCTION)_wrap.c++ is generated.

       echo

 

$(OBJECT)cmodule.so: $(OBJECT)_wrap.o

       $(CC) -shared $? -lswigpy -o $@ $(LINK)

       echo Shared object $(OBJECT)cmodule.so is made.

       echo

 

$(OBJECT)_wrap.o: $(OBJECT)_wrap.c++

       $(CC) -c $? $(OPTIMIZER) -fPIC -DHAVE_CONFIG_H $(INCLUDEPY) -I$(CPLDIR)

       echo Wrapper $(OBJECT)_wrap.c++ is compiled.

       echo

 

$(OBJECT)_wrap.c++: $(OBJECT).i vector3D.h matrix3D.h rotationMatrix.h \

                                           matrix3D.c++ rotationMatrix.c++

       $(SWIG) -c++ -c -python -shadow -I$(CPLDIR) -o $@ $(OBJECT).i

       echo Wrappers $(OBJECT).py and $(OBJECT)_wrap.c++ are generated.

       echo

 

clean clear:

       rm -f *.so $(OBJECT).py $(OBJECT).pyc *.o *_wrap.c++ *_wrap.doc core

 

Listing A1.3.0.0.1 The makefile that runs SWIG.