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

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

Для вызова функции MATLAB:

  • Передайте имя функции как matlab::engine::String.

  • Задайте входные параметры, требуемые функцией MATLAB. Можно использовать как собственные типы данных C++, так и MATLAB Data API. Для получения дополнительной информации см. MATLAB Data API.

  • Укажите количество выходов, ожидаемых от функции MATLAB. Одним из выходных параметров является выход по умолчанию. Для получения дополнительной информации смотрите Функцию вызова с несколькими возвращенными аргументами и Количество управляющих выходов.

  • Определите соответствующий возвращенный вид для результатов функции MATLAB.

  • Используйте буферы потоков для перенаправления стандартного выхода и стандартной ошибки из командного окна MATLAB на C++. Для получения дополнительной информации см. «Перенаправление Командного окна MATLAB Выхода на C++»

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

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

Функция вызова с одним возвращенным аргументом

Этот пример использует MATLAB gcd функция для нахождения наибольшего общего делителя двух чисел. The 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 в MATLAB sqrt функция. Поскольку одно из чисел в массиве отрицательное, 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 создать вектор аргументов, содержащий имена и значения в правильной последовательности.

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

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

  • Длина скалярного окна

  • Пара "имя-значение", состоящая из символьных массивов 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;
    }
}

Асинхронный вызов функции

Этот пример вызывает 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 функция для нахождения наибольших коэффициентов общего делителя и Безу из двух числовых значений проходит как входы. The gcd функция может вернуть один или три аргумента в зависимости от того, сколько выходов запросов вызов функции. В этом примере вызов MATLAB gcd функция возвращает три выхода.

По умолчанию 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 значения как входы и a 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 }); 
}

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

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

Функции MATLABEngine::feval с этими аргументами.

Исходные данные

Имя функции MATLABconst matlab::engine::String
Количество выходовconst size_t
Входные параметры для функции MATLAB (пустые)std::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, { });
    matlab::data::Array dateVector = dateTime[0];

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

    if (tZone) {
        matlab::data::Array 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;
        }
    }
}

См. также

|

Похожие темы