3

C++APIを使用してMATLAB経由で制御する必要があるDLPキットがあります。

{load_data, load_settings,display_data}たとえば、dlp_controller.cpp/.cという名前のmexファイルにC/C++を使用する関数/メソッドがあります。

私はdlp_controller();MATLABで呼び出すことができることを知っています。

このmexのメソッドをMATLABから直接呼び出す方法はありますか?

私のdlp_controller.cppmexは次のようになります。

class dlp{ ... }
dlp::dlp{ ... }
dlp::load_data{ ... }
dlp::load_settings{ ... }
dlp::display_data{ ... }

void mexFunction(int nlhs, mxArray *[],int nrhs, const mxArray *prhs[]{ ... }

dlp_controller.load_dataどういうわけかMATLABのようなメソッドを呼び出すことはできますか?注:回避策は、変数をに送信し、それとdlp_controller渡されたデータを使用して関数を内部的に呼び出すことです。

4

5 に答える 5

7

AFAIK、mexFunctionインターフェースがかなりフラットなので、これを行う簡単な方法はありません。ただし、いくつかの異なる回避策があり、それがあなたを近づけるはずだと私は考えることができます。ニーズに応じて最適なものを選択してください。

  1. dlp最も簡単なのは、mex関数でクラスのグローバルインスタンスを作成することです。mex関数の最初のパラメーターで、グローバルオブジェクトのどのメンバー関数を呼び出すかを指示する文字列を呼び出します。明らかな欠点は、mex関数をシングルトンに変えたことです。

  2. 複数のdlpインスタンスが必要な場合は、たとえばmex関数でグローバルコンテナーを作成し、MATLAB内から名前でstd::map<std::string, dlp>各インスタンスを参照できます。dlpたとえば、新しいインスタンスを作成するには、にまだ存在していない名前でmex関数を呼び出しますmap。次に、この名前、呼び出すメンバー関数を示す文字列、およびメンバー関数に渡されるパラメーターを使用してmex関数を呼び出すことができます。dlpまた、からインスタンスを消去できる規則を設定しますmap

  3. 2番目のソリューションと同様に、インスタンスに名前を付ける代わりに、各インスタンスにハンドルdlpを返すことができます。たとえば、グローバルを作成し、mex関数で新しいインスタンスを作成し、それをに追加して、割り当てられたオブジェクトへのポインターのコピーをMATLABに返します(タイプのスカラー変数に貼り付けます)。そのオブジェクトでメンバー関数を呼び出すための後続の呼び出しは、このハンドル変数をMATLABからmex関数に渡します。これを、mexファイル内で適切にキャストし、メンバー関数内で見つけて呼び出します。std::set<dlp *>dlpsetmxUINT64_CLASSset

これらのメソッドはどれも特にきれいではありませんが、mexファイル内からC++クラスのメンバー関数を呼び出すために私が知っている唯一の方法です。

于 2013-02-28T05:19:05.690 に答える
4

このMATLABCentralへの提出をご覧ください。私の知る限り、これは、MathWorkersを含む多くのニュースグループのアドバイスに基づいて開発されたベストプラクティスを示しています。

http://www.mathworks.co.uk/matlabcentral/fileexchange/38964-example-matlab-class-wrapper-for-a-c++-class

于 2013-02-28T10:35:49.757 に答える
2

最も簡単なのは、クラスオブジェクトのインスタンスを保持するMEXラッパーを設計し、そのMEXバイナリへの呼び出しをディスパッチすることです。C++でMEXラッパーを開発しようとしている人のためにライブラリを作成しました。

https://github.com/kyamagu/mexplus

これが簡単なスニペットです。

// C++ class to be wrapped.
class Database;
// Instance session storage.
template class mexplus::Session<Database>;
// Constructor.
MEX_DEFINE(new) (int nlhs, mxArray* plhs[],
                 int nrhs, const mxArray* prhs[]) {
  InputArguments input(nrhs, prhs, 1);
  OutputArguments output(nlhs, plhs, 1);
  output.set(0, Session<Database>::create(
      new Database(input.get<std::string>(0))));
}
// Destructor.
MEX_DEFINE(delete) (int nlhs, mxArray* plhs[],
                    int nrhs, const mxArray* prhs[]) {
  InputArguments input(nrhs, prhs, 1);
  OutputArguments output(nlhs, plhs, 0);
  Session<Database>::destroy(input.get(0));
}
// Member method.
MEX_DEFINE(query) (int nlhs, mxArray* plhs[],
                   int nrhs, const mxArray* prhs[]) {
  InputArguments input(nrhs, prhs, 2);
  OutputArguments output(nlhs, plhs, 1);
  const Database& database = Session<Database>::getConst(input.get(0));
  output.set(0, database.query(input.get<string>(1)));
}
// And so on...
MEX_DISPATCH
于 2014-03-17T19:14:44.620 に答える
1

それが価値があることについて、これが問題についての私の見解です。このGitHubリポジトリのMEXファイルとクラスラッパーの例をご覧ください。これは私が少し前に思いついた解決策であり、関連する質問への回答を作成しているときにこの質問を見つけました。うまくいけば、これは誰かに役立つでしょう。

設計目標

  • C++クラスの複数の永続インスタンスを管理する
  • MATLABで使用される小さな連続した整数ハンドル(キャストポインターではない)
  • リソース管理を透過的に処理します(つまり、MATLABはC ++クラスに割り当てられたメモリを一切担当しません):
    1. MATLABが「削除」アクションの発行に失敗しても、メモリリークは発生しません。
    2. MEXファイルが時期尚早にアンロードされた場合の自動割り当て解除。
  • モジュールの早期アンロードを防止します
  • マジックナンバーをチェックせずに暗黙的に検証されたハンドルの有効性
  • mexFunctionを模倣するラッパークラスや関数はなく、mexFunctionの直感的なswitch-caseブロックです。

これらの目標は、MATLABクラスに関係なく達成する必要がありますが、メモリ管理の問題に対処するのにも役立ちます。そのため、結果のMEXファイルを直接安全に使用できます(ただし、あまりエレガントではありません)。

実装の概要

C ++クラスの場合class_typemexFunctionは静的データストレージを使用してmexFunction、動的に割り当てられたクラスインスタンスへの整数ハンドルとスマートポインタの永続的な(呼び出し間)テーブルを保持します。Astd::mapはこの目的で使用され、クラスの有効なインスタンスのみが存在することが保証されている既知のハンドルの検索を容易にします。

typedef unsigned int handle_type;
std::map<handle_type, std::shared_ptr<class_type>>

Astd::shared_ptrは、(1)「削除」アクションによってテーブル要素が消去されるか、(2)MEXファイルがアンロードされるときに、割り当て解除を処理します。

MATLABクラスインスタンスが存在するときにMEXファイルがアンロードされないようにするためにmexLock、新しいC ++クラスインスタンスが作成されるたびに呼び出され、MEXファイルのロックカウントに追加されます。C ++インスタンスが削除されるたびにmexUnlock、ロックカウントから1つのロックが削除されます。

使用する

  1. [.cpp内]アクション列挙型でさまざまなアクション(たとえば、新規、削除、挿入など)を列挙します。列挙されたアクションごとに、MATLABのMEX関数に最初の引数として渡される文字列(「new」、「delete」、「insert」など)を指定します。
  2. [.cpp内]の本文のswitchステートメントの各アクションの処理をカスタマイズしmexFunctionます(たとえば、関連するC ++クラスメソッドを呼び出します)。
  3. [In .m](オプション)cppclassから派生するクラスを作成し、クラスに必要なアクションの単純なメソッドを作成します。

要件

次のC++11機能を備えた最新のコンパイラ:

  • shared_ptr
  • auto
  • enum class
  • initializer_listconst map初期化用)

Visual Studio 2013、最近のGCC(おそらくと-std=c++11)、および3.1以降のClang。

ソース

于 2015-09-11T20:52:03.483 に答える
0

ここでのユースケースに適した代替設計は、init、fcnA、fcnB、fcnC、...メソッドなどを使用してシングルトンクラスを定義し、対応する軽量ラッパーを使用して、MEXからラッパーを呼び出すことです。

例えば

class A {
  public:
     A getInstance() {
        if ( !instance )
             instance = new A(...);
        return instance;
     }

    void fcnA(T1 a1, T2 a2) {
           //yada yada
     }

  private:
    static A* instance;
};
A::instance = NULL;

//begin wrappers for marshalling to class method
A* getInstance( ) {
   return A::getInstance();
}

void fcnA(T1 a1, T2 a2) {
   getInstance()->fcnA(a1,a2);
}

//ad nauseum
于 2013-02-28T06:35:46.933 に答える