exponenta event banner

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

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

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

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

Сведения о настройке и сборке программ ядра C++ см. в разделе Сборка программ ядра C++.

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

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

При вызове функций MATLAB можно использовать собственные типы C++. MATLABEngine::feval и MATLABEngine::fevalAsync принимать определенные скалярные типы C++, переданные в качестве аргументов функции MATLAB. Для передачи массивов и других типов функциям MATLAB используется API данных MATLAB. Дополнительные сведения об этом API см. в разделе 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 }); 
}

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

См. также

|

Связанные темы