[英]Return MATLAB structure to C++ and access the elements
I'm trying to run MATLAB from C++ and return the MATLAB output in a structure to C++. I'm trying to run MATLAB from C++ and return the MATLAB output in a structure to C++. The structure could contain any number of things, including arrays of different dimensions and lengths.
该结构可以包含任意数量的东西,包括不同尺寸和长度的 arrays。 There's a similar question here , but the answer doesn't give enough detail for me to understand and extrapolate.
这里有一个类似的问题,但答案没有提供足够的细节让我理解和推断。
I'm running MATLAB using the MatlabEngine.hpp
and MatlabDataArray.hpp
.我正在使用
MatlabEngine.hpp
和MatlabDataArray.hpp
。 I need to return a lot of outputs and have tried other methods which don't quite do what I'm after.我需要返回很多输出并尝试了其他方法,这些方法并不能完全满足我的要求。 Using a structure seems the most logical / readable way to do things.
使用结构似乎是最合乎逻辑/可读性的做事方式。 I'll try to explain my case with the following examples, which are hopefully written in a way which will be most useful for anyone else with a similar problems.
我将尝试通过以下示例来解释我的案例,希望这些示例的编写方式对遇到类似问题的其他人最有用。
function output = simple_fun1(a, bc)
% Takes input values of a and an array [a,b]
b = bc(1);
c = bc(2);
sum = a+b+c;
prod = a*b*c;
output = [sum, prod; 3, 4];
This can be run using the C++ code:这可以使用 C++ 代码运行:
#include "MatlabEngine.hpp"
#include "MatlabDataArray.hpp"
#include <iostream>
int main()
{
using namespace matlab::engine;
matlab::data::ArrayFactory factory; // Create MATLAB data array factory
std::unique_ptr<MATLABEngine> matlabPtr = startMATLAB(); // Start MATLAB engine
matlabPtr->eval(u"addpath(genpath('C:/Users/...your path here...'))"); // Add the path to where MATLAB functions are.
std::vector<double> bc{ 10, 13};
std::vector<matlab::data::Array> args({
factory.CreateScalar<double>(7),
factory.CreateArray({ 1, 2 }, bc.cbegin(), bc.cend())
});
matlab::data::TypedArray<double> results = matlabPtr->feval(u"simple_fun1",args); // Run simple_fun1
std::cout << "Sum: " << results[0][0] << std::endl;
std::cout << "Prod: " << results[0][1] << std:endl;
std::cout << "Three: " << results[1][0] << std::endl;
}
This works for a single return of an n by n array.这适用于 n × n 数组的单次返回。 But if I want to return data separately, ie
function [sum, prod] = simple_fun1(a,bc)
it doesn't work.但是如果我想单独返回数据,即
function [sum, prod] = simple_fun1(a,bc)
它不起作用。
I've managed to return multiple outputs using tuples, but then I can only access the first element of the array (if it was an array output) since I've been unable to define a tuple of MATLAB arrays.我已经设法使用元组返回多个输出,但是我只能访问数组的第一个元素(如果它是数组输出),因为我无法定义 MATLAB arrays 的元组。 For example
例如
function [sum, prod] = simple_fun2(a, bc)
% Takes input values of a and an array [a,b]
b = bc(1);
c = bc(2);
sum = a+b+c;
prod = a*b*c;
std::tuple<double, double> results;
results = matlabPtr->feval< std::tuple<double, double>>(u"simple_fun2", double(7), std::vector<double>{ 10, 13}); // Just as another example of how to enter inputs in case that's helpful for anyone.
double s;
double p;
std::tie(s, p) = results;
std::cout << "Sum: " << s << ", Prod: " << p << std::endl;
Instead, I would like to write my MATLAB function so that it returns a structure, which should hopefully simplify the code for large amounts of data being passed and allow the data to have different dimensions.相反,我想编写我的 MATLAB function 以便它返回一个结构,这有望简化传递大量数据的代码并允许数据具有不同的维度。 However, I've been unable to create a working example.
但是,我一直无法创建一个工作示例。
function output = simple_fun3(a, bc)
b = bc(1);
c = bc(2);
output.sum = a+b+c;
output.prod = a*b*c;
output.a_sq = a*a;
output.b_sq = b*b;
#include "MatlabEngine.hpp"
#include "MatlabDataArray.hpp"
#include <iostream>
int main()
{
using namespace matlab::engine;
matlab::data::ArrayFactory factory; // Create MATLAB data array factory
std::unique_ptr<MATLABEngine> matlabPtr = startMATLAB(); // Start MATLAB engine
matlabPtr->eval(u"addpath(genpath('C:/Users/...your path here...'))"); // Add the path to where MATLAB functions are.
std::vector<double> bc{ 10, 13};
std::vector<matlab::data::Array> args({
factory.CreateScalar<double>(7),
factory.CreateArray({ 1, 2 }, bc.cbegin(), bc.cend())
});
matlab::data::StructArray my_matlab_struct = factory.createStructArray(matlab::data::ArrayDimensions{ 1, 4}, std::vector<std::string>{'sum', 'prod', 'a_sq', 'b_sq'});
my_matlab_struct = matlabPtr->feval(u"simple_fun3",args);
The above C++ code doesn't work and I don't understand how the structure is being defined;上面的 C++ 代码不起作用,我不明白结构是如何定义的; ie what the ArrayDimensions are dimensions of.
即 ArrayDimensions 的维度。 Any help is appreciated.
任何帮助表示赞赏。 Thanks
谢谢
After much searching I managed to solve the problem and pass structures between C++ and MATLAB.经过大量搜索,我设法解决了问题并在 C++ 和 MATLAB 之间传递结构。 The solution is based on this , but the code at the link doesn't work due to missing namespaces.
该解决方案基于this ,但由于缺少名称空间,链接处的代码不起作用。 Therefore I've put the solution below.
因此,我将解决方案放在下面。 Note: the solution assumes you already have MATLAB and C++ setup to interface with each other, which can be a whole other process depending your MATLAB version and, if you're using Visual Studio, your Visual Studio version too.
注意:该解决方案假设您已经有 MATLAB 和 C++ 设置以相互连接,这可能是一个完整的其他过程,具体取决于您的 MATLAB 版本,如果您也使用 Visual Studio 版本。
Not part of my original question, but this may be useful to someone.不是我最初的问题的一部分,但这可能对某人有用。
#include "MatlabEngine.hpp"
#include "MatlabDataArray.hpp"
#include <iostream>
#pragma comment (lib,"libmat.lib")
#pragma comment (lib,"libmx.lib")
#pragma comment (lib,"libmex.lib")
#pragma comment (lib,"libeng.lib")
int main()
{
using namespace matlab::engine;
matlab::data::ArrayFactory factory; // Create MATLAB data array factory
std::unique_ptr<MATLABEngine> matlabPtr = startMATLAB(); // Start MATLAB engine
matlabPtr->eval(u"addpath(genpath('Insert the path of any MATLAB functions you plan to use'))")
matlab::data::StructArray my_structure = factory.createStructArray({1, 1},{"x","y","z"}); // Create a structure with one element and fields x,y,z
my_structure[0]["x"] = factory.createArray({1, 3},{1., 2., 3.});
my_structure[0]["y"] = factory.createArray({1, 3},{1., 4., 9.});
my_structure[0]["z"] = factory.createArray({1, 3},{1., 8., 27.});
matlabPtr->setVariable(u"Mstruct",my_structure); // pass structure to matlab workspace
matlabPtr->eval(u"Mstruct") // show the structure exists.
// The array can be passed to a function using feval
}
The code below assumes the MATLAB engine is already set up and gets a structure returned from a MATLAB script called matlab_fun
which accepts the input(s) args
.下面的代码假定 MATLAB 引擎已经设置好,并从名为 matlab_fun 的
matlab_fun
脚本返回一个结构,该脚本接受输入args
。
matlab::data::StructArray my_matlab_struct = matlabPtr->feval(u"matlab_fun",args);
matlab::data::ArrayDimensions dims = my_matlab_struct.getDimensions();
std::cout << "Structure is: " << dims[0] << " by " << dims[1] << std::endl;
size_t numFields = my_matlab_struct.getNumberOfFields();
std::cout << "Structure has " << numFields << " fields." << std::endl;
matlab::data::Range<matlab::data::ForwardIterator, matlab::data::MATLABFieldIdentifier const> fields = my_matlab_struct.getFieldNames();
for (int i=0; i<numFields; i++){
matlab::data::TypedArray<double> data = my_matlab_struct[0][fields.begin()[i]]; // [0] for the first element of the structure. Iterates over the fields.
matlab::data::ArrayDimensions data_dims = data.getDimensions();
for (int j=0; j<data_dims[0];j++){
for (int k=0; k<data_dims[1];k++){
std::cout << data[j][k] << " ";
}
std::cout << std::endl;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.