Main Content

MEX 関数から外部リソースを管理

ソケット、センサー、ファイル、データベースなどの外部リソースに接続される MEX 関数は、これらのリソースを管理する必要があります。C++ MEX 関数はクラスとして実装されるため、コンストラクター関数とデストラクター関数を定義して、MEX 関数を繰り返し呼び出す間永続するこれらのリソースと変数を管理できます。

MEX 関数を呼び出すと、MATLAB®MexFunction クラスへのインスタンスを作成します。このオブジェクトは MATLAB セッションの間、または clear mex コマンドでオブジェクトをクリアするまで永続します。MEX 関数を繰り返し呼び出すと、入力データを処理し、完了時にリソースをリリースすることができます。

テキスト ファイルの読み取り

この MEX 関数はテキスト ファイルを開き、関数を呼び出すたびに単語を 1 つずつ読み取ります。MEX 関数を実装する MexFunction クラスによって、ファイルを開いて閉じるためのコンストラクターとデストラクターが定義されます。読み取った各単語は、その単語がファイルで出現する回数を判定するために std::unordered_map に格納されます。

コンストラクター

MexFunction コンストラクターは次の手順を実行します。

  • mexLock を呼び出して、メモリからの MEX 関数のクリアを防止します。

  • evalgetVariableを使用して、テキスト ファイルへの絶対パスを MATLAB から取得します。

  • std::ifstream 入力ストリームにテキスト ファイルを開きます。

デストラクター

クラス デストラクターはファイルを閉じます。

関数呼び出し演算子 operator()

MEX 関数を呼び出すごとにテキスト ファイルから単語が読み取られ、順序付けのないマップに追加されるか、またはその単語がマップに存在する場合は単語数が単にインクリメントされます。MEX 関数は std::ostringstream 出力ストリームを使用して、現在の単語とその数を MATLAB コマンド ウィンドウに表示します。MEX 関数のロックを解除するには、引数 ('unlock' など) を関数に渡します。

MATLAB 上の表示

メンバー関数 displayOnMATLABfevalを使用して、出力ストリームに書き込まれる文字列の指定とともに MATLAB の関数 fprintf を呼び出します。

コード リスト

#include "mex.hpp"
#include "mexAdapter.hpp"
#include <unordered_map>
#include <fstream> 

using matlab::mex::ArgumentList;
using namespace matlab::data;

class MexFunction : public matlab::mex::Function {

    // Input stream to read words from file
    std::ifstream inFile;

    // Unordered map to keep track of word count
    std::unordered_map<std::string, int> wordCount;

    // Pointer to MATLAB engine
    std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();

    // Factory to create MATLAB data arrays
    ArrayFactory factory;

public:
    MexFunction() {
        mexLock();  
        matlabPtr->eval(u"fname = fullfile(matlabroot,'extern','examples','cpp_mex','data','sonnets.txt');");
        matlab::data::CharArray fileName = matlabPtr->getVariable(u"fname");
        inFile.open(fileName.toAscii());
        if (!inFile.is_open()) {
            std::ostringstream stream;
            stream << "Failed to open sonnets.txt" << std::endl;
            displayOnMATLAB(stream);
        }
    }

    ~MexFunction() {
        if (inFile.is_open())
            inFile.close();
    }

    void operator()(ArgumentList outputs, ArgumentList inputs) {
        if (inFile.is_open() && !inFile.eof()) {
            std::string word;
            inFile >> word;
            wordCount[word]++;
            std::ostringstream stream;
            stream << "Read : " << "\"" << word << "\"" 
                << ", current count: " << wordCount[word] << std::endl;
            displayOnMATLAB(stream);
        }
        if (!inputs.empty() || !inFile.is_open()) {
            mexUnlock();
        }
    }

    void displayOnMATLAB(const std::ostringstream& stream){
        matlabPtr->feval(u"fprintf", 0, 
            std::vector<Array>({ factory.createScalar(stream.str()) }));
    }
};

sonnetWordCount.cpp のビルドと実行

ソース コード ファイル sonnetWordCount.cpp をエディターで開き、mex コマンドを使用して MEX 関数をコンパイルします。

mex sonnetWordCount.cpp

MEX 関数を繰り返し呼び出して、単語の使用回数を数えます。

>> sonnetWordCount
Read : "THE", current count: 1
>> sonnetWordCount
Read : "SONNETS", current count: 1
>> sonnetWordCount
Read : "by", current count: 1
>> sonnetWordCount
Read : "William", current count: 1
>> sonnetWordCount
Read : "Shakespeare", current count: 1
>> sonnetWordCount('unlock')

参考

関連するトピック