主要内容

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

MATLAB®C ++ MEX函数使用的数据API提供了直接在MATLAB中写入的函数的相同编写的编写语义。MEX函数可以复制传递给它的数据阵列,但此重复是原始变量的共享副本。当MEX函数修改数组中的值时,会进行单独的数据副本。

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

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

  • 修改某些结构的某些字段,该字段通过整个结构的副本传递为输入。

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

  • 修改作为输入传递的对象属性,而不创建对象的深度副本。

共享副本

在计算图像数组的平均值时,此示例代码受益于使用共享副本。将输入数组复制到常量matlab :: data :: typedArray ,它支持迭代器,金宝app允许使用基于范围的循环执行计算,但确保不复制数组。

#include "mexAdapter.hpp" using matlab::mex::ArgumentList;使用名称空间matlab::数据;class MexFunction: public matlab::mex::Function {ArrayFactory factory;public: void operator()(ArgumentList输出,ArgumentList输入){double sm = 0;const TypedArray inArray = input [0];for (auto& elem: inArray) {sm += elem;}输出[0]= factory。createScalar (sm / inArray.getNumberOfElements ());}};

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

梅克斯aveImage.cpp负载威尼斯平底渔船d = uint8(威尼斯平底渔船);%转换数据以使用aveImagem = aveimage(d)
m = 73.5487

修改MEX函数中的Cell Array

当你将单元格数组传递给MEX函数时,它的MATLAB数据API表示,matlab:: data:: CellArray,基本上是一个matlab::数据::数组包含一个matlab::数据::数组在每个细胞中。此设计使每个包含的阵列能够是共享副本,直到修改。

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

如果你修改Cell1在单元格数组B中,该单元格中的数组不再与之共享Cell1但是,在单元阵列A中。然而,所有其他小区的值仍然是共享的,以便不需要复制整个单元格阵列。

此示例显示如何将单元格数组传递给MEX函数并在单元格数组中修改一个小区,而不会导致其他单元中的数据副本。该示例将图像数据加载到MATLAB工作区中,并创建包含图像数据,标题和COLORMAP的单元格数组。

负载杜尔
Name Size Bytes Class X 648x509 2638656 double caption 2x28 112 char map 128x3 3072 double

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

durerCell {1} = X;durerCell{2} =标题;durerCell{3} =地图;

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

#include "mexAdapter.hpp" using matlab::mex::ArgumentList;使用名称空间matlab::数据;class MexFunction: public matlab::mex::Function {ArrayFactory factory;public: void operator()(ArgumentList输出,ArgumentList输入){checkArguments(输入);CellArray imageCell = std::move(input [0]);TypedArrayRef cellRef = imageCell[1];cellRef =工厂。createCharArray(“Albrecht Durer’s Melancolia with a magic square”);输出[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}
'Albrecht Durer's Melancolia with a magic square'

有关使用单元格数组的更多信息,请参见c++细胞阵列

修改MEX函数中的结构

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

structarray.类提供了访问结构字段的成员函数:

  • getfieldnames.返回提供对字段名访问的begin和end迭代器。

  • getnumberoffields.返回结构中的字段数。

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

auto fields = myStruct.getFieldNames();std::向量< matlab::数据::MATLABFieldIdentifier >字段名(fields.begin (), fields.end ());//从一个字段获取数据matlab :: data :: typedArray  Field1 = MyStruct [0] [FieldNames [0]]

通过创建正确类型的数组,为字段分配新值。

MYSTRUCT [0] [FIELDNAMES [0]] = factory.createArray <双>({1,5},{1,2,3,4,5});

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

auto fields = myStruct.getFieldNames();std::向量< matlab::数据::MATLABFieldIdentifier >字段名(fields.begin (), fields.end ());matlab :: data :: typedarrayref  field1reference = mystruct [0] [fieldnames [0]]

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

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

分配到结构字段

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

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

s =结构(“平均”{[], []},...'数据',{兰德(1000),兰迪([1,9],1000)});s = modifyStruct(年代);

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

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

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

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

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

#include "mexAdapter.hpp" using matlab::mex::ArgumentList;使用名称空间matlab::数据;class MexFunction: public matlab::mex::Function {public: void operator()(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("One input required")});} if (output .size() > 1) {matlabPtr->feval(u"error", 0, std::vector({factory. size()});createScalar("指定的输出太多")});} if (input [0]. gettype () != ArrayType::STRUCT) {matlabPtr->feval(u"error", 0, std::vector({factory. gettype () !createScalar("Input must be structure")});}}

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

void calcMean(StructArray&指导){数组工厂;auto fields = command . getfieldnames ();std::向量< MATLABFieldIdentifier >字段名(fields.begin (), fields.end ());双sm = 0;For (auto I = 0;我< 2;i++) {const TypedArray data = command [i][fieldNames[1]];For (auto& elem: data) {sm += elem;}命令[i][fieldNames[0]] =工厂。createScalar (sm / data.getNumberOfElements ()); } } };

单元格和结构数组的例子

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

另请参阅

相关话题