## [Swig-user] swigging template function for python

 [Swig-user] swigging template function for python From: Kevin Kunzmann - 2013-05-31 18:00:20 Attachments: Message as HTML ```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 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 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 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 real metric2(real *v1, real *v2, index m); template 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 real agf_calc_pdf( real **mat, real *vec, index D, index n, real var[2], real Wc ); %} template real agf_calc_pdf( real **mat, real *vec, index D, index n, real var[2], real Wc ); %template(pdf) agf_calc_pdf; 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 ```

 [Swig-user] swigging template function for python From: Kevin Kunzmann - 2013-05-31 18:00:20 Attachments: Message as HTML ```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 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 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 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 real metric2(real *v1, real *v2, index m); template 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 real agf_calc_pdf( real **mat, real *vec, index D, index n, real var[2], real Wc ); %} template real agf_calc_pdf( real **mat, real *vec, index D, index n, real var[2], real Wc ); %template(pdf) agf_calc_pdf; 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 ```