0

i want to compile following code to mexw64 using MS visual C++ compiler.

BallTree.cpp

#define MEX
#include "BallTree.h"
#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{

  // check for the right number of arguments
  if(nrhs != 2)
    mexErrMsgTxt("Takes 2 input arguments");
  if(nlhs != 1)
    mexErrMsgTxt("Outputs one result (a structure)");

//                                   points, weights
  plhs[0] = BallTree::createInMatlab(prhs[0],prhs[1]);

}

and BallTree.h

#ifndef __BALL_TREE_H
#define __BALL_TREE_H

#ifdef MEX
#include "mex.h"
#endif

#include <math.h>
#include <stdint.h>
#define FALSE 0
#define TRUE 1

double log(double);
double exp(double);
double sqrt(double);
double pow(double , double);
double fabs(double);
#define PI 3.141592653589


class BallTree {
 public:
  //typedef unsigned int index;              // define "index" type (long)
  typedef uint32_t index;              // define "index" type (long)
  const static BallTree::index NO_CHILD = (index) -1;  // indicates no further children

  /////////////////////////////
  // Constructors
  /////////////////////////////

  //BallTree( unsigned int d, index N, double* centers_,
  //     double* ranges_, double* weights_ );
#ifdef MEX
  BallTree();
  BallTree(const mxArray* structure);     // for loading ball trees from matlab

  // For creating BallTree structures in matlab:
  static mxArray*  createInMatlab(const mxArray* pts, const mxArray* wts);
#endif

  /////////////////////////////
  // Accessor Functions  
  /////////////////////////////
  BallTree::index root() const              { return 0; }
  unsigned int    Ndim() const              { return dims; }
  index Npts()                    const { return num_points; }
  index Npts(BallTree::index i)   const { return highest_leaf[i]-lowest_leaf[i]+1; }
  const double* center(BallTree::index i)   const { return centers+i*dims; }
  const double* range(BallTree::index i)    const { return ranges +i*dims; }
  double  weight(BallTree::index i)         const { return *(weights+i); }
  bool isLeaf(BallTree::index ind)          const { return ind >= num_points; }
  bool validIndex(BallTree::index ind)      const { return ((0<=ind) && (ind < 2*num_points)); }
  BallTree::index left(BallTree::index i)   const { return left_child[i]; }
  BallTree::index right(BallTree::index i)  const { return right_child[i]; }
  BallTree::index leafFirst(BallTree::index i) const { return lowest_leaf[i]; }
  BallTree::index leafLast(BallTree::index i)  const { return highest_leaf[i]; }

  // Convert a BallTree::index to the numeric index in the original data
  index getIndexOf(BallTree::index i) const { return permutation[i]; }

  void movePoints(double*);
  void changeWeights(const double *);

  // Test two sub-trees to see which is nearer another BallTree
  BallTree::index closer(BallTree::index, BallTree::index, const BallTree&,BallTree::index) const;  
  BallTree::index closer(BallTree::index i, BallTree::index j, const BallTree& other_tree) const
      { return closer(i,j,other_tree,other_tree.root()); };

  void kNearestNeighbors(index *, double *, const double *, int, int) const;

  /////////////////////////////
  // Private class f'ns
  /////////////////////////////
 protected:
#ifdef MEX
  static mxArray*  matlabMakeStruct(const mxArray* pts, const mxArray* wts);
#endif
  virtual void calcStats(BallTree::index);     // construction recursion

  unsigned int dims;             // dimension of data 
  BallTree::index num_points;     // # of points 
  double *centers;                // ball centers, dims numbers per ball 
  double *ranges;                 // bounding box ranges, dims per ball, dist from center to one side
  double *weights;                // total weight in each ball 

  BallTree::index *left_child,  *right_child;  // left, right children; no parent indices
  BallTree::index *lowest_leaf, *highest_leaf; // lower & upper leaf indices for each ball
  BallTree::index *permutation;                // point's position in the original data

  BallTree::index next;                        // internal var for placing the non-leaf nodes 

  static const char *FIELD_NAMES[];            // list of matlab structure fields
  static const int nfields;

  // for building the ball tree
  void buildBall(BallTree::index firstLeaf, BallTree::index lastLeaf, BallTree::index root);
  BallTree::index most_spread_coord(BallTree::index, BallTree::index) const;
  BallTree::index partition(unsigned int dim, BallTree::index low, BallTree::index high);
  virtual void swap(BallTree::index, BallTree::index);         // leaf-swapping function

  void select(unsigned int dimension, index position, 
               index low, index high);

  double minDist(index, const double*) const;
  double maxDist(index, const double*) const;

  // build the non-leaf nodes from the leaves
  void buildTree();
};

#endif

But I get the following compiler error: " BallTree.obj:BallTree.cpp:(.text+0x3a): undefined reference to BallTree::createInMatlab(mxArray_tag const*, mxArray_tag const*)' " also it has been noted in toolbox website that:

" MS Visual C++ has a bug in dealing with "static const" variables; I think there is a patch available, or you can change these to #defines. Operate from the class' parent directory, or add it to your MATLAB path (e.g. if you unzip to "myhome/@kde", cd in matlab to the "myhome" dir, or add it to the path.) ".

i have used another compilers such as g++ and gcc but it still fails to compile.

  • 1
    You forgot one important thing. You haven't shown us **how** you're compiling your MEX code. What is the command you're using in the MATLAB command prompt? Also, it may be prudent to share your `createInMatlab` method rather than just giving us the stub. – rayryeng Jul 18 '15 at 03:08
  • 1
    maybe you forgot to `#define MEX` in whatever cpp file has the implementation of `BallTree::createInMatlab` ? – M.M Jul 18 '15 at 03:16
  • @rayryeng i used this following command : `mex -v BallTree.cpp` – user3853830 Jul 18 '15 at 03:18
  • 1
    The VS bug with static const is for variables, not methods, and it's fixed after VS2010, if I am thinking of the same one mentioned on that side. Still, you should set static const variables in the cpp as shown [here](http://stackoverflow.com/a/2605559/2778484), although what you did with `NO_CHILD` should be OK just for `int`s. Also, where is the definition for all the `BallTree` methods? Inside BallTree.cpp, right above `mexFunction` hopefully. – chappjc Jul 18 '15 at 04:30
  • 1
    Note that if `BallTree::createInMatlab` is not defined in BallTree.cpp but somewhere else, then your command line is inadequate. If you have it in another source file, then list that after BallTree.cpp. If you have it compiled in another .obj or .lib, then list that after BallTree.cpp. – chappjc Jul 18 '15 at 04:36
  • @chappjc but if you saw in toolbox website (http://www.ics.uci.edu/~ihler/code/kde.html). this code has been compiled to .dll (matlab 32bit) and it seems this problem is'nt related to written code – user3853830 Jul 18 '15 at 21:25

1 Answers1

1

Your answer is right there in @kde/mex/makemex.m (http://www.ics.uci.edu/~ihler/code/kde.tar.gz). The build command for BallTree.cpp is:

mex BallTree.cpp cpp/BallTreeClass.cc

Note you have to include implementation file too (cpp/BallTreeClass.cc).

BallTree::createInMatlab(...) is defined on line 432 of BallTreeClass.cc.

You probably just want to run makemex.m instead of trying to do it yourself.

chappjc
  • 30,359
  • 6
  • 75
  • 132
  • thank you @chappjc as you mentioned above, i used `makemex.m` but this error still remained. furthermore, at first i compiled `BallTreeClass.cc` successfully but for mexing `BallTree.cpp` previous error was appeared. – user3853830 Jul 25 '15 at 00:04
  • @user3853830 Then show your call to makemex.m and the output. Add -v to the relevant part. You see how both files are on the same line – chappjc Jul 25 '15 at 00:10