Issue: MATLAB crashes running mex function at inconsistent points in function.
Show older comments
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 0xFF00F0A5
template<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;
}
Accepted Answer
More Answers (0)
Categories
Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!