How can I store function_handle objects in MEX code?
Mostrar comentarios más antiguos
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
Respuesta aceptada
Más respuestas (0)
Categorías
Más información sobre Write C Functions Callable from MATLAB (MEX Files) en Centro de ayuda y File Exchange.
Productos
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!