Main Content

MEX 関数の個別のスレッドからの MATLAB の呼び出し

MEX 関数は、C++ エンジンの非同期 API を使用して、ユーザーが作成したスレッドから MATLAB® を呼び出すことができます。

別々のスレッドで非同期に行われる MATLAB の呼び出しは、MATLAB の実行をブロックしません。MEX 関数は、ユーザー スレッドでの実行が継続している間に、MATLAB プロンプトに戻ることができます。エンジンの非同期 API を介してユーザー スレッドから、またはコマンド プロンプトから MATLAB 関数を呼び出すことができます。MATLAB は各スレッドからのコマンドをキューに入れ、それらを受信した順に実行します。

個別のスレッドからの MATLAB との通信

ユーザーが作成したスレッドから MATLAB を呼び出すには、次の手法を使用する MEX 関数を定義します。

  • 非同期関数呼び出しの実行スレッドを開始する (たとえば、C++11 関数 std::async を使用)。

  • C++ エンジン API を使用して、MATLAB を非同期的に呼び出す。

テキスト表示の更新例

この MEX 関数は、現在の日付と時刻を MATLAB Figure ウィンドウに表示します。日付/時刻の文字列は毎秒更新されます。MEX 関数は、std::async の呼び出しによって作成されたスレッドでの非同期更新が継続している間に、MATLAB プロンプトに戻ります。

関数 dateTimeWindow.m (MATLAB コード) は Figure ウィンドウと uicontrol text オブジェクトを作成し、日付と時刻を表示します。uicontrol と Figure の Tag プロパティには、MEX 関数からこれらのオブジェクトにアクセスするために使用される識別子が含まれています。

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

この MEX 関数は、次の操作を実行する関数 DisplayDateTime() を定義します。

  • MATLAB 関数の dateTimeWindow.m を呼び出して、Figure ウィンドウとテキスト表示を設定する。

  • datestr(now) の出力を uicontrol の String プロパティに代入することで、日付と時刻の表示を毎秒更新する。

  • uicontrol オブジェクトの有効性をテストして、Figure ウィンドウが閉じられているかどうか判断する。

  • ウィンドウおよび text オブジェクトが存在しなくなった場合は、更新ループを終了する。

MEX 関数は std::async を呼び出して、個別のスレッドでメンバー関数 DisplayDateTime() を実行します。

/* 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();
        }
    }
};

mexDateTime.cpp として保存された MEX 関数を使用するには、mex コマンドを使用してプログラムをビルドします。

mex -setup c++
mex mexDateTime.cpp
mexDateTime

MEX 関数は MEX ファイルをロックすることで、個別のスレッドが依然としてアクティブな間は、MEX 関数の再コンパイルを行わないようにします。MEX 関数は、実行の終了時に自身のロックを解除します。

個別のスレッドでの実行を終了させるには、日付と時刻のテキストを含む Figure ウィンドウを閉じるか、入力引数を指定して MEX 関数を呼び出します。以下に例を示します。

mexDateTime close

参考

| |

関連するトピック