Call MATLAB from Separate Threads in MEX Function

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.

Communicating with MATLAB from Separate Threads

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.

Example to Update the Display of Text

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

See Also

| |

Related Topics