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 Call C++ from MATLAB 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!