Hi,

I am new to swig and wanted to make the function agf_calc_pdf from the following src/agf_pdf.cxx file available in python:

#include "math.h"
#define _USE_MATH_DEFINES

struct agf_diag_param {
    unsigned int nd;    //number of squarings
    float f;            //ratio of min. weight to max.
    float W;            //total weight
};

template <class real, class index>
real metric2(real *v1, real *v2, index m)
{
    real d;
    real diff;

    d = 0;
    for (index i = 0; i < m; i++) {
        diff = v2[i] - v1[i];
        d += diff * diff;
    }
    return d;
}

template <class real, class index>
unsigned int agf_calc_w(    real *d2,         //distances squared
                            index k,       //number of distances
                            real Wc,        //objective total weight
                            real var[2],    //initial filter width
                            real *weight,    //returned weights
                            real &var_f)    //returned final filter variance
{
    unsigned int nd;                  //number of squarings of the weights
    real tw_old;                 //previous value of the total weight
    real tw;                     //current value of the total weight
    real wtint;                  //for interpolation of final weights
    //calculate the weights:
    for (index i = 0; i < k; i++) weight[i] = exp( -d2[i] / var[1] / 2);
    //repeatedly square the weights until the total is less than the threshold:
    tw = 0;
    for (index i = 0; i < k; i++) tw += weight[i];
    nd = 0;
    do {
        tw_old = tw;
        tw = 0;
        for (index i = 0; i < k; i++) {
            weight[i] *= weight[i];
            tw += weight[i];
    }
    nd++;
    } while (tw > Wc && tw < tw_old);
    //interpolate between the current and previous weight:
    wtint = (log(tw_old) - log(Wc)) / (log(tw_old) - log(tw)) / 2 + 0.5;
    //calculate the final filter width:
    var_f = var[1] / (1 << nd) / wtint;
    tw = 0;
    for (index i = 0; i < k; i++) {
        weight[i] = exp(-d2[i] / var_f / 2);
    }
    //return the number of iterations as a diagnostic parameter:
    return nd;
}

template <class real, class index>
real agf_calc_pdf(    real **mat,
                    real *vec,
                    index D,
                    index n,
                    real var[2],
                    real Wc
                    )
{
    real *d2;            //the distances (squared)
    real var_f;            //final value of the filter width (as variance)
    real tw;            //total weight
    real *weight;        //the current value for the weights
    real n1, norm;        //normalisation coeff.
    real pdf;            //final calculated value of pdf
    agf_diag_param* diag_param; // dummy output buffer
    //first we calculate all the distances:
    d2 = new real[n];
    for (index i = 0; i < n; i++) {
        d2[i] = metric2(vec, mat[i], D);
    }
    //calculate the weights using the central "engine":
    weight = new real[n];
    diag_param->nd = agf_calc_w(d2, n, Wc, var, weight, var_f);
    tw = 0;
    for (index i = 0; i < n; i++) tw += weight[i];
    //use the final filter width to normalize the pdf:
    n1 = sqrt( var_f * M_PI *2 );
    norm = 1;
    for (index i = 0; i < D; i++) norm *= n1;
    pdf = tw / norm /n;
    //set the diagnostic parameters:
    diag_param->W = tw;
    delete [] d2;
    delete [] weight;
    return pdf;
}

I wrote an interface file agf.i for the template function:

%module agf
%{
struct agf_diag_param {
    unsigned int nd;    //number of squarings
    float f;           //ratio of min. weight to max.
    float W;           //total weight
};

template <class real, class index>
real metric2(real *v1, real *v2, index m);

template <class real, class index>
unsigned int agf_calc_w(    real *d2,       //distances squared
                            index k,       //number of distances
                            real Wc,        //objective total weight
                            real var[2],    //initial filter width
                            real *weight,   //returned weights
                            real &var_f);    //returned final filter variance

template <class real, class index>
real agf_calc_pdf(  real **mat,
                    real *vec,
                    index D,
                    index n,
                    real var[2],
                    real Wc
                    );
%}

template <class real, class index>
real agf_calc_pdf(  real **mat,
                    real *vec,
                    index D,
                    index n,
                    real var[2],
                    real Wc
                    );

%template(pdf) agf_calc_pdf<double, int>;

and finally a setup.py:

#!/usr/bin/env python
from distutils.core import setup, Extension
module = Extension('_agf',
                   sources=['agf_wrap.cxx', 'src/agf_pdf.cxx'],
                   language="c++"
                   )
setup (name = 'agf',
       ext_modules = [module],
       py_modules = ["agf"]
       )
Then I invoked swig via:
swig -c++ -python agf.i

which runs without problems. python setup.py build_ext --inplace gives some warnings about unused variables, but nothing else.
I then import the generated agf.py and get an import error "ImportError: ./_agf.so: undefined symbol: _Z12agf_calc_pdfIdiET_PPS0_S1_T0_S3_S1_S0_"

any ideas?

yours,

Kevin