从 C++ 调用 MATLAB 函数
使用 matlab::engine::MATLABEngine
类的 feval 和 fevalAsync 成员函数从 C++ 调用 MATLAB® 函数。当您要将函数参数从 C++ 传递给 MATLAB 和将函数执行的结果返回给 C++ 时,请使用这些函数。这些成员函数的工作方式类似于 MATLAB feval
函数。
要调用 MATLAB 函数,需要满足以下条件:
将函数名称作为
matlab::engine::String
传递。定义 MATLAB 函数所需的输入参数。您可以使用原生 C++ 数据类型或 MATLAB 数据 API。有关详细信息,请参阅MATLAB Data API for C++。
指定 MATLAB 函数应提供的输出的数目。默认为一个输出。有关详细信息,请参阅使用多个返回参数调用函数和控制输出的数目。
为 MATLAB 函数的结果定义适当的返回类型。
使用流缓冲区将标准输出和标准错误从 MATLAB 命令行窗口重定向到 C++。有关详细信息,请参阅Redirect MATLAB Command Window Output to C++
要使用 MATLAB 基础工作区中的变量计算 MATLAB 语句,请使用 matlab::engine::MATLABEngine
eval 和 evalAsync 成员函数。这些函数使您能够在 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
函数来计算行向量的三点中心移动和,而放弃端点计算。此函数调用需要以下参数:
数值数组
标量窗长度
名称-值对组由字符数组
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。有关此 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 }); }
另请参阅
matlab::data::ArrayFactory
| matlab::engine::MATLABEngine