Main Content

从 C++ 调用 MATLAB 函数

使用 matlab::engine::MATLABEngine 类的 fevalfevalAsync 成员函数从 C++ 调用 MATLAB® 函数。当您要将函数参量从 C++ 传递给 MATLAB 和将函数执行的结果返回给 C++ 时,请使用这些函数。这些成员函数的工作方式类似于 MATLAB feval 函数。

要调用 MATLAB 函数,需要满足以下条件:

要使用 MATLAB 基础工作区中的变量计算 MATLAB 语句,请使用 matlab::engine::MATLABEngine evalevalAsync 成员函数。这些函数使您能够在 MATLAB 工作区中创建和使用变量,但不返回值。有关详细信息,请参阅Evaluate MATLAB Statements from C++

有关如何设置和编译 C++ 引擎程序的信息,请参阅编译 C++ Engine 程序的要求

调用带单一返回参量的函数

此示例使用 MATLAB gcd 函数求两个数值的最大公约数。MATLABEngine::feval 成员函数返回 gcd 函数调用的结果。

使用 matlab::data::ArrayFactory 创建两个标量 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);

此示例定义一个 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 函数时,对返回类型使用 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 函数来计算行向量的三点中心移动和,而放弃端点计算。此函数调用需要以下参量:

  • 数值数组

  • 标量窗长度

  • 名称-值对组由字符数组 Endpointdiscard 组成

以下是等效的 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 函数对传递的两个数值输入求最大公约数和 Bézout 系数。gcd 函数可以返回一个或三个参量,具体取决于函数调用请求的输出的数目。在此示例中,对 MATLAB gcd 函数的调用返回三个输出。

默认情况下,MATLABEngine::feval 假设返回值的数目为 1。因此,您必须将返回值的实际数目指定为 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::fevalMATLABEngine::fevalAsync 接受作为 MATLAB 函数参量传递的某些标量 C++ 类型。要将数组和其他类型传递给 MATLAB 函数,请使用 MATLAB 数据 API。有关此 API 的详细信息,请参阅 MATLAB Data API for C++

此示例使用 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 }); 
}

另请参阅

|

相关主题