Call MATLAB from Separate Threads in MEX Function - MATLAB & Simulink (original) (raw)

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:

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:

The MEX function calls std::async to run theDisplayDateTime() 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:

See Also

matlab::mex::Function | uicontrol | figure