C++에서 MATLAB 함수 호출하기
이 예제에서는 matlab::engine::MATLABEngine 클래스의 feval 및 fevalAsync 멤버 함수를 사용하여 C++에서 MATLAB® 함수를 호출하는 방법을 보여줍니다. C++에서 MATLAB으로 함수 인수를 전달하고 함수 실행 결과를 C++로 반환하고 싶을 때 이런 함수를 사용합니다. 이러한 멤버 함수는 MATLAB feval 함수처럼 작동합니다.
MATLAB 함수를 호출하려면 다음을 수행하십시오.
함수 이름을
matlab::engine::String으로 전달합니다.MATLAB 함수에 필요한 입력 인수를 정의합니다. 기본 C++ 데이터형 또는 MATLAB Data API를 사용할 수 있습니다. 자세한 내용은 C++용 MATLAB Data API 항목을 참조하십시오.
MATLAB 함수의 예상 출력값 개수를 지정합니다. 디폴트 값은 출력값 한 개입니다. 자세한 내용은 반환되는 인수가 여러 개인 함수 호출하기 항목과 출력값 개수 제어하기 항목을 참조하십시오.
MATLAB 함수의 결과에 대한 적절한 반환 유형을 정의합니다.
스트림 버퍼를 사용하여 MATLAB 명령 창에 표시되는 표준 출력값과 표준 오차를 C++로 리디렉션합니다. 자세한 내용은 Redirect MATLAB Command Window Output to C++ 항목을 참조하십시오.
MATLAB 기본 작업 공간에 있는 변수를 사용하여 MATLAB 명령문을 실행하려면 matlab::engine::MATLABEngine eval 및 evalAsync 멤버 함수를 사용하십시오. 이러한 함수는 사용자가 MATLAB 작업 공간에서 변수를 만들고 사용하는 것을 허용하지만 값을 반환하지는 않습니다. 자세한 내용은 Evaluate MATLAB Statements from C++ 항목을 참조하십시오.
C++ 엔진 프로그램을 설정하고 빌드하는 방법에 관한 자세한 내용은 Requirements to Build C++ Engine Applications 항목을 참조하십시오.
반환되는 인수가 하나인 함수 호출하기
이 예제에서는 MATLAB gcd 함수를 사용하여 두 숫자의 최대공약수를 찾습니다. 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);이 예제에서는 double형의 배열을 MATLAB sqrt 함수로 전달하기 위해 matlab::data::TypedArray를 정의합니다. 배열에 있는 숫자 중 하나가 음수이므로, 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 함수를 호출하여 두 다항식을 곱합니다. 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 함수를 사용하여 입력값으로 전달되는 두 숫자형 값의 최대공약수와 베주 계수를 구합니다. gcd 함수는 함수 호출에서 요청하는 출력값의 개수에 따라 한 개 또는 세 개의 인수를 반환할 수 있습니다. 이 예제에서는 MATLAB gcd 함수에 대한 호출이 세 개의 출력값을 반환합니다.
기본적으로, MATLABEngine::feval은 반환되는 값의 개수가 한 개인 것으로 가정합니다. 따라서 반환되는 값의 실제 개수를 MATLABEngine::feval에 대한 두 번째 인수로 지정해야 합니다.
이 예제에서, MATLABEngine::feval은 gcd 함수 호출의 세 결과를 포함한 std::vector를 반환합니다. 반환되는 값은 정수 스칼라입니다.
#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++ 유형으로 함수 호출하기
MATLAB 함수를 호출할 때 기본 C++ 유형을 사용할 수 있습니다. MATLABEngine::feval과 MATLABEngine::fevalAsync는 MATLAB 함수 인수로 전달되는 특정 스칼라 C++ 유형을 허용합니다. 배열과 기타 유형을 MATLAB 함수로 전달하려면 MATLAB Data API를 사용하십시오. 이 API에 대한 자세한 내용은 C++용 MATLAB Data API 항목을 참조하십시오.
이 예제에서는 int16_t 값을 입력값으로 사용하고 std::tuple을 사용하여 MATLAB gcd 함수의 결과를 반환합니다.
다음은 이와 동일한 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 secondsstate = 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 });
}표준 출력값 또는 오류에 대한 스트림 버퍼 유형 전달하기
이 예제에서는 MATLABEngine feval 멤버 함수에 의한 MATLAB 함수 실행으로 생성된 출력값을 반환하기 위해 문자열 버퍼를 정의합니다. 이 함수는 matlab::engine::StreamBuffer에서 파생된 버퍼 outputBufStream과 errBufStream을 사용하여, plot 함수의 출력값을 C++로 반환합니다. 이 예제에서는 입력값 없이 plot을 호출하고, 그로 인해 MATLAB 오류가 생성됩니다.
#include "MatlabEngine.hpp"
#include "MatlabDataArray.hpp"
#include <iostream>
using namespace matlab::engine;
using StringBuffer = std::basic_stringbuf<char16_t>;
void printFromBuf(const std::shared_ptr<StringBuffer> strBuf) {
// Print buffer contents
auto text = strBuf->str();
std::cout << "*" << convertUTF16StringToUTF8String(text)
<< "*" << std::endl;
}
int main() {
// Start MATLAB engine
std::unique_ptr<MATLABEngine> matlabPtr = startMATLAB();
// Create the buffers
std::shared_ptr<StringBuffer> outputBuf = std::make_shared<std::basic_stringbuf<char16_t>>();
std::shared_ptr<StringBuffer> errBuf = std::make_shared<std::basic_stringbuf<char16_t>>();
// Cast to exact type of buffer that variadic feval accepts
const std::shared_ptr<StreamBuffer> outputBufStream = outputBuf;
const std::shared_ptr<StreamBuffer> errBufStream = errBuf;
// Print MATLAB command window output
matlabPtr->feval<void>(u"disp", outputBufStream, errBufStream, "Hello world!");
printFromBuf(outputBuf);
// Call the plot function without input values
try {
matlabPtr->feval<void>(u"plot", outputBufStream, errBufStream);
} catch (const matlab::engine::Exception& e) {
printFromBuf(errBuf); // print MATLAB error output
}
return 0;
}시스템 명령 프롬프트에서 프로그램을 호출합니다.
main*Hello world!
*
*Error using plot
Not enough input arguments.
*참고 항목
matlab::data::ArrayFactory | matlab::engine::MATLABEngine | matlab::engine::StreamBuffer