主要内容

类型、单元格和结构数组中的数据访问

MATLAB®c++ MEX函数使用的数据API提供了与直接在MATLAB中编写的函数相同的写时复制语义。MEX函数可以复制传递给它的数据数组,但这个副本是原始变量的共享副本。当MEX函数修改数组中的值时,将生成数据的单独副本。

当您调用一个MEX函数时,matlab::数据::数组输入是传递给MEX函数的MATLAB变量的共享副本。共享副本提供了一个优势,当MEX函数:

  • 不修改传递给MEX函数的大数组。

  • 修改作为输入传递的结构的某些字段,而不复制整个结构。

  • 修改作为输入传递的单元格数组中的单元格,而不引起单元格数组的深度复制

  • 修改作为输入传递的对象属性,而不生成对象的深层副本。

共享副本

在计算图像数组的平均值时,该示例代码得益于共享副本的使用。将输入数组复制到常量matlab::数据::TypedArray < T >,它支持迭代器,万博1manbetx允许使用基于范围的循环执行计算,但确保不复制数组。

使用matlab::mex::ArgumentList包含“mexAdapter.hpp”;使用命名空间matlab::data;类MexFunction:公共matlab::mex::Function {ArrayFactory工厂;public: void operator()(ArgumentList输出,ArgumentList输入){double sm = 0;const TypedArray inArray = inputs[0];for (auto&elem: inArray) {sm += elem;}输出[0]= factory。createScalar(sm / inArray.getNumberOfElements());}};

将MEX函数的源代码保存在一个名为aveImage.cpp。可以使用此函数查找地形数据数组的平均值。加载topo.mat将文件导入MATLAB工作空间,并将数据数组传递给MEX函数。

墨西哥人aveImage.cpp负载威尼斯平底渔船D = uint8(topo);%转换数据使用aveImagem = aveImage(d)
M = 73.5487

在MEX函数中修改单元格数组

当您将单元格数组传递给MEX函数时,它的MATLAB数据API表示,matlab:: data:: CellArray,本质上是一个matlab::数据::数组,其中包含matlab::数据::数组在每个单元格中。这种设计使每个包含的数组在修改之前都是一个共享副本。

当修改MEX函数中单元格数组的单元格时,只有该单元格中包含的数组是非共享的,而不是整个单元格数组。例如,假设您将单元格数组A复制到单元格数组b。每个单元格的值都是共享的。

数组A中的每个单元格都映射到数组B中的一个单元格。

如果你修改Cell1在单元格数组B中,该单元格中的数组不再被共享Cell1但是,所有其他单元格的值保持共享,因此整个单元格数组不需要复制。

数组A中除Cell1外的每个单元格都映射到数组B中的一个单元格。

此示例演示如何将单元格数组传递给MEX函数,并修改单元格数组中的一个单元格,而不复制其他单元格中的数据。该示例将图像数据加载到MATLAB工作空间中,并创建包含图像数据、标题和配色图的单元格数组。

负载杜勒
名称大小字节类X 648x509 2638656双标题2x28 112字符映射128x3 3072双

将每个变量分配到不同的单元格。

durerCell{1} = X;durerCell{2} =标题;durerCell{3} = map;

这个MEX函数使用std::移动将输入单元格数组移动到matlab:: data:: CellArray,提供访问单个单元格的功能。唯一修改的数据是存储在单元格数组的一个单元格中的标题。要修改该单元格:

使用matlab::mex::ArgumentList包含“mexAdapter.hpp”;使用命名空间matlab::data;类MexFunction:公共matlab::mex::Function {ArrayFactory工厂;public: void operator()(ArgumentList outputs, ArgumentList inputs) {checkArguments(inputs);CellArray imageCell = std::move(输入[0]);TypedArrayRef cellRef = imageCell[1];cellRef = factory。createCharArray(“Albrecht Durer的忧郁与魔方”);输出[0]= imageCell;} void checkArguments(ArgumentList输入){std::shared_ptr matlabPtr = getEngine(); if (inputs[0].getType() != ArrayType::CELL) { matlabPtr->feval(u"error", 0, std::vector ({ factory.createScalar("Input must be cell array") })); } } };

将此代码保存在一个名为modifyCellArray.cpp,生成MEX文件,然后调用该函数。

墨西哥人modifyCellArray.cppdurerCell = modifyCellArray(durerCell);

返回的单元格数组包含在MEX函数中分配的新字符数组。

durerCell {2}
丢勒的《魔方的忧郁》

有关使用单元格数组的详细信息,请参见c++单元格数组

在MEX函数中修改结构

MATLAB数据API定义matlab:: data:: StructArray用MATLAB表示结构体数组。每个字段在StructArray本身包含一个数组。因此,可以修改字段StructArray传递给一个MEX函数,而不会导致整个数组被复制。未修改的字段仍然与输入数组字段共享。

StructArray类提供成员函数来访问结构的字段:

  • getFieldNames返回开始和结束迭代器,提供对字段名的访问。

  • getNumberOfFields返回结构中的字段数。

例如,您可以生成字段名的向量,并使用这些名称访问结构中的数据。这段代码假设字段包含一个类型的数组

auto fields = myStruct.getFieldNames();std::vector fieldNames(fields.begin(), fields.end());//从一个字段中获取数据matlab::data::TypedArray field1 = myStruct[0][fieldNames[0]]

通过创建正确类型的数组将新值赋给字段。

myStruct[0][fieldNames[0]] =工厂。createArray({1,5}, {1,2,3,4,5});

创建对结构的字段的引用matlab::数据::参考< T >,您可以将其传递给访问字段中的值的函数。引用使您能够获取字段的值,为字段分配新值,并创建另一个引用相同值的数组。例如,这段代码创建了对包含双精度数组的字段的引用。

auto fields = myStruct.getFieldNames();std::vector fieldNames(fields.begin(), fields.end());matlab::data::TypedArrayRef field1Reference = myStruct[0][fieldNames[0]]

使用此引用为字段分配新值。

field1Reference =工厂。createArray({1,5}, {1,2,3,4,5});

分配到结构字段

本例将MATLAB结构传递给MEX函数。该结构包含两个大数据字段和两个包含由MEX函数分配的标量值的字段。MEX函数计算每个数组中数字的平均值,并将这些值赋给平均各自结构的字段。

此MATLAB代码创建结构数组并将其传递给从modifyStruct.cpp这里描述的文件。

S = struct(“平均”{[], []},...“数据”,{兰德(1000),兰迪([1,9],1000)});s = modifyStruct(s);

这是MexFunction::操作符()函数。它执行以下操作:

  • 调用checkArgument函数检查输入和输出的大小和类型。

  • 将输入赋值给amatlab:: data:: StructArray变量。

  • 调用calcMean函数来计算平均值。

  • 将更新后的结构数组分配给MEX函数输出。

使用matlab::mex::ArgumentList包含“mexAdapter.hpp”;使用命名空间matlab::data;类MexFunction:公共matlab::mex::函数{公共:无效操作符()(ArgumentList输出,ArgumentList输入){checkArguments(输出,输入);StructArray指示(输入[0]);calcMean(指导);输出[0]=指令;}

checkArguments函数执行以下检查:

  • 输入的数量等于1。

  • 输出个数不大于1。

  • 输入为MATLAB结构数组。

void checkArguments(ArgumentList输出,ArgumentList输入){std::shared_ptr matlabPtr = getEngine();ArrayFactory工厂;if (input .size() != 1) {matlabPtr->feval(u"error", 0, std::vector<数组>({factory. size() !)createScalar("一个输入必须")}));} if (output .size() > 1) {matlabPtr->feval(u"error", 0, std::vector<数组>({工厂。createScalar("指定的输出太多")}));} if(输入[0]. gettype () != ArrayType::STRUCT) {matlabPtr->feval(u"error", 0, std::vector<数组>({工厂。createScalar("输入必须是结构")}));}}

calcMean函数中每组数字的平均值数据字段并将这些值赋给平均各自结构的字段。

void calcMean(StructArray& instruction) {ArrayFactory工厂;auto fields = directive . getfieldnames ();std::vector fieldNames(fields.begin(), fields.end()));双sm = 0;For (auto I = 0;I < 2;i++) {const TypedArray data = instruction [i][fieldNames[1]];For (auto& elem: data) {sm += elem;}指示[i][fieldNames[0]] =工厂。createScalar(sm / data.getNumberOfElements()); } } };

单元格和结构数组的例子

对于使用单元格和结构数组的相关示例,请在MATLAB编辑器中打开此源文件phonebook.cpp

另请参阅

相关的话题