从 C++ 调用 MATLAB 函数

目录

从 C++ 调用 MATLAB 函数

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

使用名称/值参数调用函数

以异步方式调用函数

使用多个返回参数调用函数

用原生 C++ 类型调用函数

控制输出的数目


从 C++ 调用 MATLAB 函数

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

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

  • 将函数名称作为 matlab::engine::String 传递。

  • ​定义 MATLAB 函数所需的输入参数。可以使用原生 C++ 数据类型或 MATLAB 数据 API。有关详细信息,可以参考MATLAB 数据 API。​

  • ​指定 MATLAB 函数应提供的输出的数目。默认为一个输出。有关详细信息,可以参考使用多个返回参数调用函数和控制输出的数目。​

  • 为 MATLAB 函数的结果定义适当的返回类型。

  • 使用流缓冲区将标准输出和标准错误从 MATLAB 命令行窗口重定向到 C++。有关详细信息,可以参考Redirect MATLAB Command Window Output to C++​

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

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

  • 数值数组

  • 标量窗口长度

  • 名称-值对组由字符数组 Endpoint 和 discard 组成

        以下是等效的 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::feval 和 MATLABEngine::fevalAsync 接受作为 MATLAB 函数参数传递的某些标量 C++ 类型。要将数组和其他类型传递给 MATLAB 函数,可以使用MATLAB 数据 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 函数的行为可能会有所不同。某些函数不返回任何输出或返回指定数量的输出。

        例如,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。

输入

MATLAB 函数名称const 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, { });
    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;
        }
    }
}
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值