I am working on a mex function that utilizes a C++ class for operating with SQL. When the a.Search(MX_SR) is executed (which searches the database and returns a set of object IDs satisfying a range for sorting indices), the mex function crashes a different points. The two points it has halted at is after "Search matlab method entered" and immediately before return in class_interface_mex. I have a hunch it is something to do with not allocating/deallocating the std::vector variables. I am not sure exactly how to tackle it however. Several other articles mention issues with a compilation variable (on Windows). I am running on Ubuntu 14.04, MATLAB 2015a. Compiled using c++4.9.
Uses std library, boost, mysql libraries in underlying functions (i.e. DBInterface.hpp, DBInterface.cpp).
class_interface_mex.cpp:
#include "mex.h"#include "class_handle.hpp"// The class that we are interfacing to#include "DBInterface.h"#include "ML_Utility.cpp"#include "DBInterface.cpp"void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){ // Get the command string char cmd[64]; if (nrhs < 1 || mxGetString(prhs[0], cmd, sizeof(cmd))) mexErrMsgTxt("First input should be a command string less than 64 characters long."); // New if (!strcmp("new", cmd)) { // Check parameters if (nlhs != 1) mexErrMsgTxt("New: One output expected."); // Return a handle to a new C++ instance plhs[0] = convertPtr2Mat<DBInterface>(new DBInterface); return; } // Check there is a second input, which should be the class instance handle if (nrhs < 2) mexErrMsgTxt("Second input should be a class instance handle."); // Delete if (!strcmp("delete", cmd)) { // Destroy the C++ object destroyObject<DBInterface>(prhs[1]); // Warn if other commands were ignored if (nlhs != 0 || nrhs != 2) mexWarnMsgTxt("Delete: Unexpected arguments ignored."); return; } // Get the class instance pointer from the second input DBInterface *DB_instance = convertMat2Ptr<DBInterface>(prhs[1]); // Call the various class methods // Add2Buffer if (!strcmp("Add2Buffer", cmd)) { // Check parameters if (nlhs < 0 || nrhs < 4) mexErrMsgTxt("Add2Buffer: Unexpected arguments."); // Call the method std::vector<double> Found_Objects; std::vector<double> New_Objects; Found_Objects = MX2DoubleVector(prhs[2]); New_Objects = MX2DoubleVector(prhs[3]); DB_instance->Add2Buffer(Found_Objects, New_Objects); return; } // Build if (!strcmp("Build", cmd)) { // Check parameters if (nlhs > 0 || nrhs > 2) mexErrMsgTxt("Build: Unexpected arguments."); // Call the method DB_instance->Build(); return; } // Search if (!strcmp("Search", cmd)) { mexPrintf("\n Search Entered."); // Check parameters if (nlhs != 1 || nrhs > 3) mexErrMsgTxt("\n Search: Unexpected arguments."); std::vector<int> SearchRange; std::vector<int> Res; mexPrintf("\n Search Variables Defined."); SearchRange = MX2IntVector(prhs[2]); mexPrintf("\n Search: Search Range is of size: %d", SearchRange.size()); if (SearchRange.size()!=40) mexErrMsgTxt("\n Search: Failure to convert Search Range to proper size"); for (int i=0; i<SearchRange.size(); i++) mexPrintf("\n Search: Search Range at %d is %d", i, SearchRange.at(i)); mexPrintf("\n Search: Size Check Complete."); Res = DB_instance->Search(SearchRange); mexPrintf("\n Search: Res is of size: %d", Res.size()); mexPrintf("\n Search: Res at first index is: %d", Res.at(0)); mexPrintf("\n Search: C++ program run complete."); plhs[0] = IntVector2MX(Res); mexPrintf("\n Conversion from Integer Vector to mxArray complete."); return; } // Got here, so command not recognized mexErrMsgTxt("Command not recognized."); }
DatabaseInterface.m:
%CLASS_INTERFACE Example MATLAB class wrapper to an underlying C++ class
classdef DatabaseInterface < handle properties (SetAccess = private, Hidden = true) objectHandle; % Handle to the underlying C++ class instance
end methods %%Constructor - Create a new C++ class instance
function this = DatabaseInterface(varargin) this.objectHandle = class_interface_mex('new', varargin{:}); end %%Destructor - Destroy the C++ class instance
function delete(this) class_interface_mex('delete', this.objectHandle); end %%Build - Build B and M.
function varargout = Build(this, varargin) [varargout{1:nargout}] = class_interface_mex('Build', this.objectHandle, varargin{:}); end %%Search - Search DB given an object.
function varargout = Search(this, varargin) display('Search matlab method entered.'); [varargout{1:nargout}] = class_interface_mex('Search', this.objectHandle, varargin{:}); end %%Add2Buffer - Add buffer to DB.
function varargout = Add2Buffer(this, varargin) [varargout{1:nargout}] = class_interface_mex('Add2Buffer', this.objectHandle, varargin{:}); end end end
class_handle.hpp:
#ifndef __CLASS_HANDLE_HPP__#define __CLASS_HANDLE_HPP__#include "mex.h"#include <stdint.h>#include <string>#include <cstring>#include <typeinfo>#define CLASS_HANDLE_SIGNATURE 0xFF00F0A5template<class base> class class_handle{public: class_handle(base *ptr) : ptr_m(ptr), name_m(typeid(base).name()) { signature_m = CLASS_HANDLE_SIGNATURE; } ~class_handle() { signature_m = 0; delete ptr_m; } bool isValid() { return ((signature_m == CLASS_HANDLE_SIGNATURE) && !strcmp(name_m.c_str(), typeid(base).name())); } base *ptr() { return ptr_m; }private: uint32_t signature_m; std::string name_m; base *ptr_m;};template<class base> inline mxArray *convertPtr2Mat(base *ptr){ mexLock(); mxArray *out = mxCreateNumericMatrix(1, 1, mxUINT64_CLASS, mxREAL); *((uint64_t *)mxGetData(out)) = reinterpret_cast<uint64_t>(new class_handle<base>(ptr)); return out;}template<class base> inline class_handle<base> *convertMat2HandlePtr(const mxArray *in){ if (mxGetNumberOfElements(in) != 1 || mxGetClassID(in) != mxUINT64_CLASS || mxIsComplex(in)) mexErrMsgTxt("Input must be a real uint64 scalar."); class_handle<base> *ptr = reinterpret_cast<class_handle<base> *>(*((uint64_t *)mxGetData(in))); if (!ptr->isValid()) mexErrMsgTxt("Handle not valid."); return ptr;}template<class base> inline base *convertMat2Ptr(const mxArray *in){ return convertMat2HandlePtr<base>(in)->ptr();}template<class base> inline void destroyObject(const mxArray *in){ delete convertMat2HandlePtr<base>(in); mexUnlock();}#endif // __CLASS_HANDLE_HPP__
ML_Utility.cpp:
/* * ML_Utility.cpp * * Created on: Jun 1, 2015 * Author: derek */#include "mex.h"#include <vector>#include <string>#include "matrix.h"mxArray * DoubleVector2MX(const std::vector<double>& v){ mxArray * mx = mxCreateDoubleMatrix(1,v.size(), mxREAL); std::copy(v.begin(), v.end(), mxGetPr(mx)); return mx; }std::vector<double> MX2DoubleVector(const mxArray prhs[]){ std::vector<double> Vec; const mxArray *Cons_prhs = prhs; size_t NRow = mxGetN(Cons_prhs); size_t NCol = mxGetM(Cons_prhs); std::string::size_type sz; for (long int nn=0; nn<NRow; nn++){ for (long int mm=0; mm<NCol; mm++){ Vec.push_back((double)mxGetPr(Cons_prhs)[0]); mxGetPr(Cons_prhs)[0]+=1; } } return Vec;}mxArray * IntVector2MX(const std::vector<int>& v){ mxArray *mx; mexPrintf("\n IntVector2MX: Pointer defined."); mx = mxCreateNumericMatrix(1, v.size(),mxINT32_CLASS, mxREAL); mexPrintf("\n IntVector2MX: Numeric array created."); std::copy(v.begin(), v.end(), mxGetPr(mx)); mexPrintf("\n IntVector2MX: Pointer to Data allocated."); mexPrintf("\n IntVector2MX: Copy Complete."); return mx; }std::vector<int> MX2IntVector(const mxArray prhs[]){ std::vector<int> Vec; unsigned int *pr; pr = (unsigned int *)mxGetData(prhs); mexPrintf("\n MX2IntVector: Variables defined."); size_t NElem = mxGetNumberOfElements(prhs); mexPrintf("\n MX2IntVector: Size aquired."); std::string::size_type sz; for (long int nn=0; nn<NElem; nn++){ mexPrintf("\n MX2IntVector: Entered copy iteration."); Vec.push_back(*pr++); mexPrintf("\n MX2IntVector: Copy Iteration Complete"); //mxGetPr(pr)[0]+=1; mexPrintf("\n MX2IntVector: Pointer Increment complete."); } if (Vec.size()!=(NElem)) mexErrMsgTxt("\n MX2IntVector: Failure to populate vector. "); return Vec; }
Best Answer