Search All of the Math Forum:
Views expressed in these public forums are not endorsed by
Drexel University or The Math Forum.
|
|
|
|
Re: Making C++ objects persistent between mex calls, and robust.
Posted:
Oct 2, 2012 11:44 AM
|
|
I have recently discovered that if you call clear functions or clear all (which will also clear the functions from memory), when you have created one or more C++ objects in a mex file and passed the pointers back to MATLAB, then MATLAB will crash. You therefore still need to ensure that the relevant mex files are not cleared from memory using the mexLock function.
I have updated my header file to include this functionality, and to improve the checking of the pointer (with usage examples at the bottom):
#include "mex.h" #include <stdint.h> #include <string>
#define CLASS_HANDLE_SIGNATURE 0xFF00F0A5 template<class base> class class_handle { public: class_handle(base *ptr) : ptr_m(ptr), name_m(typeid(base).raw_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).raw_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(); }
// Code for init_mex() - ISM3D is my C++ object class, but you use your own ISM3D *ism = new ISM3D(var1, var2); plhs[0] = convertPtr2Mat<ISM3D>(ism);
// Code for clear_mex() destroyObject<ISM3D>(prhs[0]);
// Code for action_mex ISM3D *ism = convertMat2Ptr<ISM3D>(prhs[0]); ism->action();
|
|
|
|