C++ からの MATLAB 関数の呼び出し
次の例では、matlab::engine::MATLABEngine
クラスのメンバー関数fevalAsyncとfevalを使用して、C++ から MATLAB® 関数を呼び出す方法を説明します。これらの関数を使用して、関数引数を C++ から MATLAB に渡し、関数の実行結果を C++ に返します。これらのメンバー関数は、MATLAB 関数 feval
のように動作します。
MATLAB 関数を呼び出すには、以下を実行します。
関数名を
matlab::engine::String
として渡します。MATLAB 関数に必要な入力引数を定義します。ネイティブ C++ データ型または MATLAB データ API のいずれかを使用できます。詳細については、C++ 用の MATLAB データ APIを参照してください。
期待される MATLAB 関数からの出力数を指定します。既定は出力数 1 です。詳細については、戻り引数を複数指定した関数の呼び出しおよび出力数のコントロールを参照してください。
MATLAB 関数の結果の適切な戻り値の型を定義します。
ストリーム バッファーを使用して標準出力と標準エラーを MATLAB コマンド ウィンドウから C++ へリダイレクトします。詳細については、MATLAB コマンド ウィンドウの出力を C++ にリダイレクトを参照してください。
MATLAB ベース ワークスペースの変数を使用して MATLAB ステートメントを評価するには、matlab::engine::MATLABEngine
のメンバー関数evalとevalAsyncを使用します。これらの関数を使用すると MATLAB ワークスペースで変数を作成して使用できるようになりますが、その場合、値は返されません。詳細については、C++ からの MATLAB ステートメントの評価を参照してください。
C++ エンジン プログラムを設定およびビルドする方法の詳細については、C++ エンジン プログラムのビルド要件を参照してください。
戻り引数を 1 つ指定した関数の呼び出し
この例では、MATLAB 関数 gcd
を使用して 2 つの数字の最大公約数を見つけます。メンバー関数 MATLABEngine::feval
は gcd
関数呼び出しの結果を返します。
matlab::data::ArrayFactory
を使用して 2 つのスカラー int16_t
引数を作成します。引数を std::vector
の MATLABEngine::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 点の中心移動合計値を計算し、端点での計算を破棄します。この関数呼び出しは、以下の引数を必要とします。
数値配列
ウィンドウの長さ (スカラー)
文字配列
Endpoint
とdiscard
から構成される名前と値の引数
以下は等価の 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::vector
が MATLABEngine::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 });
}
参考
matlab::data::ArrayFactory
| matlab::engine::MATLABEngine