/* ---------------------------------------------------------------------------- * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) * See LICENSE for the license information * -------------------------------------------------------------------------- */ /** * @file matlab.h * @brief header file to be included in MATLAB wrappers * @date 2008 * @author Frank Dellaert * * wrapping and unwrapping is done using specialized templates, see * http://www.cplusplus.com/doc/tutorial/templates.html */ #include #include using gtsam::Vector; using gtsam::Matrix; extern "C" { #include } #include #include #include #include #include #include #include #include using namespace std; using namespace boost; // not usual, but for conciseness of generated code // start GTSAM Specifics ///////////////////////////////////////////////// // to enable Matrix and Vector constructor for SharedGaussian: #define GTSAM_MAGIC_GAUSSIAN // end GTSAM Specifics ///////////////////////////////////////////////// #ifdef __LP64__ // 64-bit Mac #define mxUINT32OR64_CLASS mxUINT64_CLASS #else #define mxUINT32OR64_CLASS mxUINT32_CLASS #endif //***************************************************************************** // Utilities //***************************************************************************** void error(const char* str) { mexErrMsgIdAndTxt("wrap:error", str); } mxArray *scalar(mxClassID classid) { mwSize dims[1]; dims[0]=1; return mxCreateNumericArray(1, dims, classid, mxREAL); } void checkScalar(const mxArray* array, const char* str) { int m = mxGetM(array), n = mxGetN(array); if (m!=1 || n!=1) mexErrMsgIdAndTxt("wrap: not a scalar in ", str); } //***************************************************************************** // Check arguments //***************************************************************************** void checkArguments(const string& name, int nargout, int nargin, int expected) { stringstream err; err << name << " expects " << expected << " arguments, not " << nargin; if (nargin!=expected) error(err.str().c_str()); } //***************************************************************************** // wrapping C++ basis types in MATLAB arrays //***************************************************************************** // default wrapping throws an error: only basis types are allowed in wrap template mxArray* wrap(Class& value) { error("wrap internal error: attempted wrap of invalid type"); } // specialization to string // wraps into a character array template<> mxArray* wrap(string& value) { return mxCreateString(value.c_str()); } // specialization to char template<> mxArray* wrap(char& value) { mxArray *result = scalar(mxUINT32OR64_CLASS); *(char*)mxGetData(result) = value; return result; } // specialization to unsigned char template<> mxArray* wrap(unsigned char& value) { mxArray *result = scalar(mxUINT32OR64_CLASS); *(unsigned char*)mxGetData(result) = value; return result; } // specialization to bool template<> mxArray* wrap(bool& value) { mxArray *result = scalar(mxUINT32OR64_CLASS); *(bool*)mxGetData(result) = value; return result; } // specialization to size_t template<> mxArray* wrap(size_t& value) { mxArray *result = scalar(mxUINT32OR64_CLASS); *(size_t*)mxGetData(result) = value; return result; } // specialization to int template<> mxArray* wrap(int& value) { mxArray *result = scalar(mxUINT32OR64_CLASS); *(int*)mxGetData(result) = value; return result; } // specialization to double -> just double template<> mxArray* wrap(double& value) { return mxCreateDoubleScalar(value); } // wrap a const Eigen vector into a double vector mxArray* wrap_Vector(const gtsam::Vector& v) { int m = v.size(); mxArray *result = mxCreateDoubleMatrix(m, 1, mxREAL); double *data = mxGetPr(result); for (int i=0;i double vector template<> mxArray* wrap(gtsam::Vector& v) { return wrap_Vector(v); } // const version template<> mxArray* wrap(const gtsam::Vector& v) { return wrap_Vector(v); } // wrap a const Eigen MATRIX into a double matrix mxArray* wrap_Matrix(const gtsam::Matrix& A) { int m = A.rows(), n = A.cols(); #ifdef DEBUG_WRAP mexPrintf("wrap_Matrix called with A = \n", m,n); gtsam::print(A); #endif mxArray *result = mxCreateDoubleMatrix(m, n, mxREAL); double *data = mxGetPr(result); // converts from column-major to row-major for (int j=0;j double matrix template<> mxArray* wrap(gtsam::Matrix& A) { return wrap_Matrix(A); } // const version template<> mxArray* wrap(const gtsam::Matrix& A) { return wrap_Matrix(A); } //***************************************************************************** // unwrapping MATLAB arrays into C++ basis types //***************************************************************************** // default unwrapping throws an error // as wrap only supports passing a reference or one of the basic types template T unwrap(const mxArray* array) { error("wrap internal error: attempted unwrap of invalid type"); } // specialization to string // expects a character array // Warning: relies on mxChar==char template<> string unwrap(const mxArray* array) { char *data = mxArrayToString(array); if (data==NULL) error("unwrap: not a character array"); string str(data); mxFree(data); return str; } // Check for 64-bit, as Mathworks says mxGetScalar only good for 32 bit template T myGetScalar(const mxArray* array) { switch (mxGetClassID(array)) { case mxINT64_CLASS: return (T) *(int64_t*) mxGetData(array); case mxUINT64_CLASS: return (T) *(uint64_t*) mxGetData(array); default: // hope for the best! return (T) mxGetScalar(array); } } // specialization to bool template<> bool unwrap(const mxArray* array) { checkScalar(array,"unwrap"); return myGetScalar(array); } // specialization to char template<> char unwrap(const mxArray* array) { checkScalar(array,"unwrap"); return myGetScalar(array); } // specialization to unsigned char template<> unsigned char unwrap(const mxArray* array) { checkScalar(array,"unwrap"); return myGetScalar(array); } // specialization to int template<> int unwrap(const mxArray* array) { checkScalar(array,"unwrap"); return myGetScalar(array); } // specialization to size_t template<> size_t unwrap(const mxArray* array) { checkScalar(array, "unwrap"); return myGetScalar(array); } // specialization to double template<> double unwrap(const mxArray* array) { checkScalar(array,"unwrap"); return myGetScalar(array); } // specialization to Eigen vector template<> gtsam::Vector unwrap< gtsam::Vector >(const mxArray* array) { int m = mxGetM(array), n = mxGetN(array); if (mxIsDouble(array)==false || n!=1) error("unwrap: not a vector"); #ifdef DEBUG_WRAP mexPrintf("unwrap< gtsam::Vector > called with %dx%d argument\n", m,n); #endif double* data = (double*)mxGetData(array); gtsam::Vector v(m); for (int i=0;i gtsam::Matrix unwrap< gtsam::Matrix >(const mxArray* array) { if (mxIsDouble(array)==false) error("unwrap: not a matrix"); int m = mxGetM(array), n = mxGetN(array); #ifdef DEBUG_WRAP mexPrintf("unwrap< gtsam::Matrix > called with %dx%d argument\n", m,n); #endif double* data = (double*)mxGetData(array); gtsam::Matrix A(m,n); // converts from row-major to column-major for (int j=0;j mxArray* wrap_shared_ptr(boost::shared_ptr< Class >* shared_ptr, const char *classname) { mxArray* mxh = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL); *reinterpret_cast**> (mxGetPr(mxh)) = shared_ptr; //return mxh; return create_object(classname, mxh); } template mxArray* wrap_collect_shared_ptr(boost::shared_ptr< Class >* shared_ptr, const char *classname) { mxArray* mxh = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL); *reinterpret_cast**> (mxGetPr(mxh)) = shared_ptr; //return mxh; return create_collect_object(classname, mxh); } template boost::shared_ptr unwrap_shared_ptr(const mxArray* obj, const string& className) { mxArray* mxh = mxGetProperty(obj,0,"self"); if (mxGetClassID(mxh) != mxUINT32OR64_CLASS || mxIsComplex(mxh) || mxGetM(mxh) != 1 || mxGetN(mxh) != 1) error( "Parameter is not an Shared type."); boost::shared_ptr* spp = *reinterpret_cast**> (mxGetPr(mxh)); return *spp; }