Main Content

C++ からの MATLAB 関数の呼び出し

次の例では、matlab::engine::MATLABEngine クラスのメンバー関数fevalAsyncfevalを使用して、C++ から MATLAB® 関数を呼び出す方法を説明します。これらの関数を使用して、関数引数を C++ から MATLAB に渡し、関数の実行結果を C++ に返します。これらのメンバー関数は、MATLAB 関数 feval のように動作します。

MATLAB 関数を呼び出すには、以下を実行します。

MATLAB ベース ワークスペースの変数を使用して MATLAB ステートメントを評価するには、matlab::engine::MATLABEngine のメンバー関数evalevalAsyncを使用します。これらの関数を使用すると MATLAB ワークスペースで変数を作成して使用できるようになりますが、その場合、値は返されません。詳細については、C++ からの MATLAB ステートメントの評価を参照してください。

C++ エンジン プログラムを設定およびビルドする方法の詳細については、C++ エンジン プログラムのビルド要件を参照してください。

戻り引数を 1 つ指定した関数の呼び出し

この例では、MATLAB 関数 gcd を使用して 2 つの数字の最大公約数を見つけます。メンバー関数 MATLABEngine::fevalgcd 関数呼び出しの結果を返します。

matlab::data::ArrayFactory を使用して 2 つのスカラー int16_t 引数を作成します。引数を std::vectorMATLABEngine::feval に渡します。

#include "MatlabEngine.hpp"
#include "MatlabDataArray.hpp"
#include <iostream>

void callFevalgcd() {

    // Pass vector containing MATLAB data array scalar
    using namespace matlab::engine;

    // Start MATLAB engine synchronously
    std::unique_ptr<MATLABEngine> matlabPtr = startMATLAB();

    // Create MATLAB data array factory
    matlab::data::ArrayFactory factory;

    // Pass vector containing 2 scalar args in vector    
    std::vector<matlab::data::Array> args({
        factory.createScalar<int16_t>(30),
        factory.createScalar<int16_t>(56) });

    // Call MATLAB function and return result
    matlab::data::TypedArray<int16_t> result = matlabPtr->feval(u"gcd", args);
    int16_t v = result[0];
    std::cout << "Result: " << v << std::endl;
}

ネイティブ C++ 型を使用して MATLABEngine::feval を呼び出すことができます。そのためには、MATLABEngine::feval への呼び出しの戻り値の型を以下のように指定しなければなりません。

feval<type>(...)

たとえば、次での戻り値の型は int になります。

int cresult = matlabPtr->feval<int>(u"gcd", 30, 56);

この例では、matlab::data::TypedArray を定義して double 型の配列を MATLAB 関数 sqrt に渡します。配列の数値の 1 つが負であるため、MATLAB は結果として複素数配列を返します。したがって、戻り値の型を matlab::data::TypedArray<std::complex<double>> として定義します。

#include "MatlabEngine.hpp"
#include "MatlabDataArray.hpp"
#include <iostream>

void callFevalsqrt() {
    // Call MATLAB sqrt function on array

    using namespace matlab::engine;

    // Start MATLAB engine synchronously
    std::unique_ptr<MATLABEngine> matlabPtr = startMATLAB();

    // Create  MATLAB data array factory
    matlab::data::ArrayFactory factory;

    // Define a four-element array 
    matlab::data::TypedArray<double> const argArray = 
        factory.createArray({ 1,4 }, { -2.0, 2.0, 6.0, 8.0 });

    // Call MATLAB function
    matlab::data::TypedArray<std::complex<double>> const results = 
        matlabPtr->feval(u"sqrt", argArray);

    // Display results
    int i = 0;
    for (auto r : results) {
        double a = argArray[i++];
        double realPart = r.real();
        double imgPart = r.imag();
        std::cout << "Square root of " << a << " is " << 
            realPart << " + " << imgPart << "i" << std::endl;
    }
}

MATLAB 関数を呼び出すときに matlab::data::Array を戻り値の型として使用すると安全です。たとえば、matlab::data::Array を戻り値として使用して前述の例を記述することができます。

void callFevalsqrt() {
    // Call MATLAB sqrt function on array

    using namespace matlab::engine;

    // Start MATLAB engine synchronously
    std::unique_ptr<MATLABEngine> matlabPtr = startMATLAB();

    // Create MATLAB data array factory
    matlab::data::ArrayFactory factory;

    // Define a four-element array 
    matlab::data::Array const argArray = 
        factory.createArray({ 1,4 }, { -2.0, 2.0, 6.0, 8.0 });

    // Call MATLAB function    
    matlab::data::Array results = matlabPtr->feval(u"sqrt", argArray);

    // Display results 
    for (int i = 0; i < results.getNumberOfElements(); i++) {
        double a = argArray[i];
        std::complex<double> v = results[i];
        double realPart = v.real();
        double imgPart = v.imag();
        std::cout << "Square root of " << a << " is " <<
            realPart << " + " << imgPart << std::endl;
    }
}

名前と値の引数を使用した関数の呼び出し

一部の MATLAB 関数は、オプションとして名前と値の引数を受け入れます。名前は文字配列、値は任意の型の値にすることができます。std::vector を使用して、名前と値を正しい順序で含んだ引数のベクトルを作成します。

この例では、MATLAB 関数 movsum を呼び出して行ベクトルの 3 点の中心移動合計値を計算し、端点での計算を破棄します。この関数呼び出しは、以下の引数を必要とします。

  • 数値配列

  • ウィンドウの長さ (スカラー)

  • 文字配列 Endpointdiscard から構成される名前と値の引数

以下は等価の MATLAB コードです。

A = [4 8 6 -1 -2 -3 -1 3 4 5];
M = movsum(A,3,'Endpoints','discard');

MATLAB 関数のこれらの引数を含んだ std::vector として、引数を MATLABEngine::feval に渡します。matlab::data::ArrayFactory を使用して各引数を作成します。

void callFevalmovsum() {
    //Pass vector containing various types of arguments

    using namespace matlab::engine;

    // Start MATLAB engine synchronously
    std::unique_ptr<MATLABEngine> matlabPtr = startMATLAB();

    // Create  MATLAB data array factory
    matlab::data::ArrayFactory factory;

   // Create a vector of input arguments
    std::vector<matlab::data::Array> args({
        factory.createArray<double>({ 1, 10 }, { 4, 8, 6, -1, -2, -3, -1, 3, 4, 5 }),
        factory.createScalar<int32_t>(3),
        factory.createCharArray("Endpoints"),
        factory.createCharArray("discard")
    });

    // Call MATLAB function 
    matlab::data::TypedArray<double> const result = matlabPtr->feval(u"movsum", args);

    // Display results    
    int i = 0;
    for (auto r : result) {
        std::cout << "results[" << i++ << "] = " << r << std::endl;
    }
}

非同期での関数の呼び出し

この例では、MATLAB 関数 conv を呼び出して 2 つの多項式を乗算します。MATLABEngine::fevalAsync を呼び出した後、FutureResult::get を使用して MATLAB から結果を取得します。

#include "MatlabDataArray.hpp"
#include "MatlabEngine.hpp"
#include <iostream>

static void callFevalAsync() {
    //Call MATLAB functions asynchronously

    using namespace matlab::engine;

    // Start MATLAB engine synchronously
    std::unique_ptr<MATLABEngine> matlabPtr = startMATLAB();

    // Create MATLAB data array factory
    matlab::data::ArrayFactory factory;

     // Create input argument arrays
    std::vector<matlab::data::Array> args({
        factory.createArray<double>({ 1, 3 },{ 1, 0, 1 }),
        factory.createArray<double>({ 1, 2 },{ 2, 7 }) 
    });
    String func(u"conv");

    // Call function asnychronously
    FutureResult<matlab::data::Array> future = matlabPtr->fevalAsync(func, args);
    
    // Get results
    matlab::data::TypedArray<double> results = future.get();

    // Display results
    std::cout << "Coefficients: " << std::endl;
    for (auto r : results) {
        std::cout << r << " " << std::endl;
    }
}

戻り引数を複数指定した関数の呼び出し

この例では、MATLAB 関数 gcd を使用して、入力として渡される 2 つの数値から最大公約数とベズー係数を求めます。関数 gcd は、関数呼び出しで要求される出力の数によって、1 つまたは 3 つの引数を返すことができます。この例では、MATLAB 関数 gcd への呼び出しは 3 つの出力を返します。

既定では、MATLABEngine::feval は 1 つの戻り値を想定しています。したがって、実際の戻り値の数を MATLABEngine::feval への 2 番目の引数として指定しなければなりません。

この例では、関数 gcd の呼び出しによる 3 つの結果を含んだ std::vectorMATLABEngine::feval から返されます。戻り値はスカラー整数になります。

#include "MatlabDataArray.hpp"
#include "MatlabEngine.hpp"
#include <iostream>

void multiOutput() {
    //Pass vector containing MATLAB data array array

    using namespace matlab::engine;

    // Start MATLAB engine synchronously
    std::unique_ptr<MATLABEngine> matlabPtr = startMATLAB();
    std::cout << "Started MATLAB Engine" << std::endl;

    //Create MATLAB data array factory
    matlab::data::ArrayFactory factory;

    //Create vector of MATLAB data array arrays
    std::vector<matlab::data::Array> args({
        factory.createScalar<int16_t>(30),
        factory.createScalar<int16_t>(56)
    });

    //Call gcd function, get 3 outputs
    const size_t numReturned = 3;
    std::vector<matlab::data::Array> result = matlabPtr->feval(u"gcd", numReturned, args);

    //Display results
    for (auto r : result) {
        std::cout << "gcd output: " << int16_t(r[0]) << std::endl;
    }
}

ネイティブ C++ 型を指定した関数呼び出し

ネイティブ C++ 型を使用して MATLAB 関数を呼び出すことができます。MATLABEngine::feval および MATLABEngine::fevalAsync は、MATLAB 関数引数として渡された特定のスカラー C++ 型を受け入れます。配列およびその他の型を MATLAB 関数に渡す場合は、MATLAB データ API を使用します。この API の詳細については、C++ 用の MATLAB データ APIを参照してください。

この例では、int16_t 値を入力として使用し、MATLAB 関数 gcd から結果を返すために std::tuple を使用します。

以下は等価の MATLAB コードです。

[G,U,V] = gcd(int16(30),int16(56));
#include "MatlabEngine.hpp"
#include <iostream>
#include <tuple>

void multiOutputTuple() {
    //Return tuple from MATLAB function call

    using namespace matlab::engine;

    // Start MATLAB engine synchronously
    std::unique_ptr<MATLABEngine> matlabPtr = startMATLAB();

    //Call MATLAB gcd function    
    std::tuple<int16_t, int16_t, int16_t> nresults;
    nresults = matlabPtr->feval<std::tuple<int16_t, int16_t, int16_t>>
        (u"gcd", int16_t(30), int16_t(56));

    // Display results
    int16_t G;
    int16_t U;
    int16_t V;
    std::tie(G, U, V) = nresults;
    std::cout << "GCD : " << G << ", "
              << "Bezout U: " << U << ", "
              << "Bezout V: " << V << std::endl;
}

メンバー関数の構文についての特定情報の詳細については、matlab::engine::MATLABEngine を参照してください。

出力数のコントロール

MATLAB 関数の動作は、要求された出力の数によって異なる場合があります。一部の関数では、出力を返さないようにすることや、指定数の出力を返すことができます。

たとえば、MATLAB 関数 pause を実行すると、指定した秒数だけ実行が停止します。しかし、出力引数を指定して pause を呼び出すと、一時停止されずに、ただちにステータス値が返されます。

pause(20) % Pause for 20 seconds
state = pause(20); % No pause, return pause state

この例では、出力を割り当てずに pause を呼び出します。出力に void が指定された場合、MATLAB は実行を 20 秒間停止します。

#include "MatlabEngine.hpp"

void voidOutput() {
    // No output from feval
    using namespace matlab::engine;

    // Start MATLAB engine synchronously    
    std::unique_ptr<MATLABEngine> matlabPtr = startMATLAB();

    // Call pause function with no output    
    matlabPtr->feval<void>(u"pause", 20); 
}

次の MATLABEngine::feval への呼び出しでは、MATLAB 関数引数を std::vector<matlab::data::Array> として定義するシグネチャを使用します。出力引数を割り当てない場合、MATLAB は実行を 20 秒間停止します。

#include "MatlabDataArray.hpp"
#include "MatlabEngine.hpp"

void zeroOutput() {
    // No output from feval

    using namespace matlab::engine;

    // Start MATLAB engine synchronously    
    std::unique_ptr<MATLABEngine> matlabPtr = startMATLAB();

    //Create MATLAB data array factory
    matlab::data::ArrayFactory factory;

    // Call pause function with no output    
    matlab::data::Array arg = factory.createScalar<int16_t>(20);
    const size_t numReturned = 0;
    matlabPtr->feval(u"pause", numReturned, { arg }); 
}

参考

|

関連するトピック