MEX functions can call MATLAB® from user-created threads using the C++ Engine asynchronous API.
Calls made asynchronously to MATLAB on a separate thread do not block MATLAB execution. The MEX function can return to the MATLAB prompt while execution on the user thread continues. You can call MATLAB functions from the user thread via the engine asynchronous API or from the command prompt. MATLAB queues the commands from each thread and executes them in the order received.
To call MATLAB from user-created threads, define a MEX function that uses these techniques:
Start a thread of execution for asynchronous function calls, for example with the C++11 std::async
function.
Use the C++ Engine API to make asynchronous calls to MATLAB.
This MEX function displays the current date and time in a MATLAB figure window. The date/time string updates every second. The MEX function returns to the MATLAB prompt while the asynchronous updates continue on the thread created by the call to std::async
.
The dateTimeWindow.m
function (MATLAB code) creates a figure window and a uicontrol
text object to display the date and time. The Tag
properties of the uicontrol and the figure contain identifiers used to access these objects from the MEX function.
function dateTimeWindow windowHandle = figure('MenuBar','none',... 'ToolBar','none',... 'Name','Current Date and Time',... 'NumberTitle','off',... 'Units','normalized',... 'Position',[.01 .01 .25 .05],... 'Tag','mexDateTimeHandle',... 'HandleVisibility','off'); uicontrol('Parent',windowHandle,... 'Style','text',... 'Tag','date_time',... 'String',datestr(now),... 'Units','normalized',... 'Position',[0 0 1 1],... 'FontSize',28); end
This MEX function defines the DisplayDateTime()
function to perform these operations:
Calls the dateTimeWindow.m
MATLAB function to set up the figure window and text display.
Updates the display of the date and time once per second by assigning the output of the expression datestr(now)
to the uicontrol String
property.
Tests the validity of the uicontrol object to determine if the figure window has been closed.
Exits the update loop if the window and text object no longer exist.
The MEX function calls std::async
to run the DisplayDateTime()
member function on a separate thread.
/* Uses asynchronous Engine API to display date-time string
* Calls MATLAB dateTimeWindow.m function to create figure
* and uicontrol objects. Updates the date and time once
* per second. Run asynchronously on a separate thread
*/
#include "mex.hpp"
#include "mexAdapter.hpp"
#include <thread>
#include <future>
class MexFunction : public matlab::mex::Function {
private:
std::future<void> voidStdFuture;
std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
bool isRunning = false;
public:
void DisplayDateTime( ) {
matlab::data::ArrayFactory factory;
matlabPtr->evalAsync(u"dateTimeWindow;");
while (isRunning) {
matlabPtr->evalAsync(u"set(findall(0,'Tag','date_time'),
'String',datestr(now));");
std::vector<matlab::data::Array> args({
factory.createScalar<double>(0),
factory.createCharArray("Tag"),
factory.createCharArray("date_time"),
});
matlab::engine::FutureResult<matlab::data::Array> fresult;
fresult = matlabPtr->fevalAsync(u"findall", args);
matlab::data::Array result = fresult.get();
isRunning = !result.isEmpty();
if (!isRunning) { matlabPtr->evalAsync(u"mexDateTime close"); }
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void operator()(matlab::mex::ArgumentList outputs,
matlab::mex::ArgumentList inputs) {
if (inputs.size() == 0) {
mexLock();
if(!isRunning) {
isRunning = true;
voidStdFuture = std::async(std::launch::async,
&MexFunction::DisplayDateTime, this);
}
}
else {
isRunning = false;
matlabPtr->eval(u"close(findall(0,'Tag','mexDateTimeHandle'))");
mexUnlock();
}
}
};
To use the MEX function saved as mexDateTime.cpp
, use the mex
command to build the program.
mex -setup c++ mex mexDateTime.cpp mexDateTime
The MEX function locks the MEX file to prevent attempts to recompile the MEX function while the separate thread is still active. The MEX function unlocks itself when you end execution.
To end execution on the separate thread, close the figure window containing the date and time text or call the MEX function with an input argument. For example:
mexDateTime close
figure
| matlab::mex::Function
| uicontrol