How can I store function_handle objects in MEX code?
Show older comments
Hi,
I'm writing a MEX file to create a Qt application instance in order to get an event loop to be able to use QIODevice modules depending on it.
I can create an delete the QApplication instance. Now I would like to store a function_handle object in my mex file in order use it to trigger callbacks in Matlab.
Below are snippets of the interesting parts.
messageHandler is a static method getting called when a message comes in the system. From this method, I'm trying to use FEVAL, passing as first argument the function_handle I store from matlab, the message type as double, and the message string.
I stepped through the code and already checked instance->m_messageHandlerCallback is the same pointer as when called in the mexFunction. In mexFunction mxIsClass succeeds, but fails in CoreLibrary::messageHandler, so obviously I'm doing something illegal.
C++
void CoreLibrary::messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
CoreLibrary* instance = CoreLibrary::instance();
const char* localMsg = msg.toLatin1().constData();
mxArray *prhs[3];
if (!mxIsClass(static_cast<const mxArray*>(instance->m_messageHandlerCallback), "function_handle"))
{
mexErrMsgTxt("Third input argument is not a function handle.");
return;
}
prhs[0] = instance->m_messageHandlerCallback;
prhs[1] = convertInt32ToMat(static_cast<int>(type));
prhs[2] = mxCreateString(msg.toLatin1().constData());
mexCallMATLAB(0, nullptr, 3, prhs, "feval");
if (type == QtFatalMsg)
{
abort();
}
mxDestroyArray(prhs[1]);
mxDestroyArray(prhs[2]);
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
// Get the command string
char cmd[64];
mxGetString(prhs[(nrhs == 1) ? 0 : 1], cmd, sizeof(cmd));
// New
if (!strcmp("new", cmd))
{
if (nrhs != 1)
{
mexErrMsgTxt("new: 1 inputs expected");
return;
}
if (nlhs != 1)
{
mexErrMsgTxt("new: 1 output expected");
return;
}
CoreLibrary::inc();
CoreLibrary* module = CoreLibrary::instance();
plhs[0] = convertPtr2Mat<CoreLibrary>(module);
qInstallMessageHandler(&CoreLibrary::messageHandler);
return;
}
// setMessageHandlerCallback
if (!strcmp("setMessageHandlerCallback", cmd))
{
CHK_MEX_ARGS("setMessageHandlerCallback", 3, 0);
const mxArray* functionHandle = prhs[2];
if (!mxIsClass(functionHandle, "function_handle"))
{
mexErrMsgTxt("Third input argument is not a function handle.");
return;
}
module->setMessageHandlerCallback(const_cast<mxArray*>(functionHandle));
}
// setMessageHandlerCallback
if (!strcmp("test", cmd))
{
CHK_MEX_ARGS("setMessageHandlerCallback", 3, 0);
char message[1024] = "";
mxGetString(prhs[2], message, 1024);
qDebug() << message;
}
// Delete
if (!strcmp("delete", cmd))
{
CHK_MEX_ARGS("delete", 2, 0);
CoreLibrary::dec();
return;
}
}
Matlab
classdef Core < handle
properties (SetAccess = private, Hidden = true)
objectHandle; % Handle to the underlying C++ class instance
end
methods
function self = Core(folder, appName)
self.objectHandle = CoreMex('new');
self.setMessageHandler(@self.defaultMessageHandler);
%...
self.defaultMessageHandler(4, 'Application starts');
end
function delete(self)
fclose(self.file);
CoreMex(self.objectHandle, 'delete');
end
function setMessageHandler(self, messageHandler)
self.messageHandler = messageHandler;
CoreMex(self.objectHandle, 'setMessageHandlerCallback', messageHandler);
end
function test(self)
CoreMex(self.objectHandle, 'test', 'Hello');
end
function defaultMessageHandler(self, type, message)
% ...
end
end
end
Test code
g = Core();
g.test();
Does anyone know how these function_handle can be stored on the MEX side?
Thanks
Accepted Answer
More Answers (0)
Categories
Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!