Main Content

C++에서 MATLAB 함수 호출하기

matlab::engine::MATLABEngine 클래스의 fevalfevalAsync 멤버 함수를 사용하여 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 evalevalAsync 멤버 함수를 사용하십시오. 이러한 함수는 사용자가 MATLAB 작업 공간에서 변수를 만들고 사용하는 것을 허용하지만 값을 반환하지는 않습니다. 자세한 내용은 Evaluate MATLAB Statements from C++ 항목을 참조하십시오.

C++ 엔진 프로그램을 설정하고 빌드하는 방법에 관한 자세한 내용은 C++ 엔진 프로그램 빌드를 위한 요구 사항 항목을 참조하십시오.

반환되는 인수가 하나인 함수 호출하기

이 예제에서는 MATLAB gcd 함수를 사용하여 두 숫자의 최대공약수를 찾습니다. MATLABEngine::feval 멤버 함수는 gcd 함수 호출의 결과를 반환합니다.

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);

이 예제에서는 double형의 배열을 MATLAB sqrt 함수로 전달하기 위해 matlab::data::TypedArray를 정의합니다. 배열에 있는 숫자 중 하나가 음수이므로, MATLAB은 복소수 배열을 결과로 반환합니다. 따라서 반환되는 유형을 matlab::data::TypedArray<std::complex<double>>로 정의합니다.

#include "MatlabDataArray.hpp"
#include "MatlabEngine.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::vectorMATLABEngine::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 함수를 사용하여 입력값으로 전달되는 두 숫자형 값의 최대공약수와 베주 계수(Bézout coefficient)를 구합니다. gcd 함수는 함수 호출에서 요청하는 출력값의 개수에 따라 한 개 또는 세 개의 인수를 반환할 수 있습니다. 이 예제에서는 MATLAB gcd 함수에 대한 호출이 세 개의 출력값을 반환합니다.

기본적으로, MATLABEngine::feval은 반환되는 값의 개수가 한 개인 것으로 가정합니다. 따라서 반환되는 값의 실제 개수를 MATLABEngine::feval에 대한 두 번째 인수로 지정해야 합니다.

이 예제에서, MATLABEngine::fevalgcd 함수 호출의 세 결과를 포함한 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::fevalMATLABEngine::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 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 }); 
}

참고 항목

|

관련 항목