Вызов функций MATLAB с C++

Вызовите функции MATLAB® с C++ с помощью feval и fevalAsync функций членства класса matlab::engine::MATLABEngine. Используйте эти функции когда это необходимо, чтобы передать аргументы функции от C++ до MATLAB и возвратить результат функционального выполнения на C++. Эти функции членства работают как функция feval MATLAB.

Вызывать функцию MATLAB:

Чтобы оценить переменные использования выражений MATLAB в базовом рабочем пространстве MATLAB, используйте eval matlab::engine::MATLABEngine и evalAsync функции членства. Эти функции позволяют вам создать и использовать переменные в рабочем пространстве MATLAB, но сделать не возвращаемые значения. Для получения дополнительной информации смотрите, Оценивают Выражения MATLAB с C++.

Для получения информации о том, как установить и создать программы механизма C++, видит Сборку Программы Engine C++.

Вызывание функции с Одиночным возвращаемым параметром

Этот пример использует функцию gcd MATLAB, чтобы найти наибольший общий делитель двух чисел. Функция членства MATLABEngine::feval возвращает результаты вызова функции gcd.

Используйте matlab::data::ArrayFactory, чтобы создать два скалярных аргумента int16_t. Передайте аргументы MATLABEngine::feval в std::vector.

#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;
}

Можно вызвать MATLABEngine::feval с помощью нативных типов C++. Для этого необходимо задать возвращенный тип с вызовом MATLABEngine::feval как:

feval<type>(...)

Например, возвращенным типом является int здесь:

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

Этот пример задает matlab::data::TypedArray, чтобы передать массив типа double к функции sqrt MATLAB. Поскольку одно из чисел в массиве отрицательно, 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::data::Array для возвращенных типов при вызове функций MATLAB. Например, можно записать предыдущий пример с помощью 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, чтобы создать вектор аргументов, содержащих имена и значения в правильной последовательности.

Этот пример кода вызывает функцию movsum MATLAB, чтобы вычислить движущуюся сумму в центре с тремя точками вектора - строки, отбрасывая вычисления конечной точки. Этот вызов функции требует этих аргументов:

  • Числовой массив

  • Скалярная длина окна

  • Пара "имя-значение", состоящая из символьных массивов Endpoint и discard

Вот эквивалентный код MATLAB:

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

Передайте аргументы MATLABEngine::feval как std::vector, содержащий эти аргументы для функции MATLAB. Создайте каждый аргумент с помощью 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;
    }
}

Вызывание функции асинхронно

Этот пример вызывает функцию conv MATLAB, чтобы умножить два полинома. После вызова 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;
    }
}

Вызывание функции с Многократными возвращаемыми параметрами

Этот пример кода использует функцию gcd MATLAB, чтобы найти наибольший общий делитель и коэффициенты Bézout от этих двух передач числовых значений как входные параметры. Функция gcd может возвратить или один или три аргумента, в зависимости от того, сколько выходных параметров запрашивает вызов функции. В этом примере вызов функции gcd MATLAB возвращает три выходных параметра.

По умолчанию MATLABEngine::feval принимает, что количество возвращенных значений является тем. Поэтому необходимо задать фактическое количество возвращенных значений в качестве второго аргумента к MATLABEngine::feval.

В этом примере MATLABEngine::feval возвращает std::vector, содержащий три результата вызова функции gcd. Возвращенные значения являются скалярными целыми числами.

#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 признают, что определенные скалярные типы C++ передали в качестве аргументов функции MATLAB. Чтобы передать массивы и другие типы к функциям MATLAB, используйте MATLAB Data API. Для получения дополнительной информации об этом API см. MATLAB Data API.

Этот пример использует значения int16_t в качестве входных параметров и std::tuple, чтобы возвратить результаты функции gcd MATLAB.

Вот эквивалентный код 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 могут вести себя по-другому в зависимости от количества выходных параметров, которые требуют. Некоторые функции не могут возвратить выходные параметры или конкретное количество выходных параметров.

Например, функция pause MATLAB содержит выполнение для конкретного количества секунд. Однако, если вы вызываете 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 }); 
}

Функция clock MATLAB возвращает текущую дату и время как вектор даты. Если вы присваиваете два выходных параметров, clock возвращает второй выходной параметр как булево значение, указывающее, является ли это Летнее время в зоне системного времени.

Этот пример вызывает функцию clock с одним выводом или двумя выходными параметрами, в зависимости от значения входного параметра. Второй аргумент, переданный вызову MATLABEngine::feval, определяет сколько выходных параметров, чтобы запросить от clock.

Вызовите MATLABEngine::feval с этими аргументами.

Входные параметры

Имя функции MATLABconst matlab::engine::String
Количество выходных параметровconst size_t
Входные параметры для (пустой) функции MATLABstd::vector<matlab::data::Array>

Выходные параметры

Все выходные параметры std::vector<matlab::data::Array>
#include "MatlabDataArray.hpp"
#include "MatlabEngine.hpp"
#include <iostream>
void varOutputs(const bool tZone) {

    using namespace matlab::engine;

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

    // Define number of outputs
    size_t numReturned(0);
    if (tZone) {
        numReturned = 2;
    } else {
        numReturned = 1;
    }
    std::vector<matlab::data::Array> dateTime = matlabPtr->feval(u"clock", numReturned, { });
    auto dateVector = dateTime[0];

    // Display results
    for (int i = 0; i < 6; i++) {
        std::cout << double(dateVector[i]) << " ";
    }

    if (tZone) {
        auto DTS = dateTime[1];
        if (bool(DTS[0])) {
            std::cout << "It is Daylight Saving Time" << std::endl;
        }
        else {
          std::cout << "It is Standard Time" << std::endl;
        }
    }
}

Смотрите также

|

Похожие темы