主要内容

本页采用了机器翻译。点击此处可查看最新英文版本。

C# 中的 Marshal MATLAB 结构 (structs)

R2026a

结构(或 structs)是 MATLAB® 数组,其元素通过文本字段指示符访问。

结构由称为字段的数据容器组成。每个字段存储某种 MATLAB 数据类型的数组。每个字段都有一个唯一的名称。

创建 MATLAB 结构体

MATLAB 结构体是名称-值对的有序列表。您可以通过定义 .NET 结构体或类在 C# 中表示它们,只要它具有与 MATLAB 结构体相对应的 public 字段或属性。.NET 结构体或类中的字段或属性可以具有可转换为任何 MATLAB 数据类型(包括元胞数组或其他结构体)的值。本文中的示例同时使用了 .NET struct 和类。

在 MATLAB 中,创建一个包含 name、score 和 grade 的结构体来存储学生的信息。

S.name = 'Ed Plum';
S.score = 83;
S.grade = 'B+' 
此代码创建一个具有三个字段的标量结构体 (S)。
S = 
    name: 'Ed Plum'
    score: 83
    grade: 'B+'
您可以通过在结构体 S 中插入其他元素来创建多维结构体数组。以下代码创建一个尺寸为 (1,3) 的结构体数组。
S(2).name = 'Tony Miller';
S(2).score = 91;
S(2).grade = 'A-';
S(3).name = 'Mark Jones';
S(3).score = 85;
S(3).grade = 'A-';

使用 .NET 结构和类

您可以创建 .NET 结构体和类来在数据和 MATLAB 结构体之间编组数据。

.NET struct Student 是 .NET struct 的一个示例,它使用 sortstudents 字段和属性将 .NET 类型编组为 MATLAB 函数的输入,例如 public。请注意公开声明的字段 name 以及属性 grade 和 score。

除了使用 .NET struct 之外,请注意以下事项:

  • Student 也可以定义为一个类。

  • 尽管在此示例中使用了 public 字段和属性的组合,但您也可以仅使用字段或属性。

public struct Student
{
    public string name;
    private string gr;
    private int sc;

    public string grade
    {
        get { return gr; }
        set { gr = value; }            
    }

    public int score
    {
        get { return sc; }
        set { sc = value; }
    }

    public override string ToString()
    {
        return name + " : " + grade + " : " + score;
    }
}

注意

请注意,此示例为了方便使用了 ToString。它对于编组来说不是必需的。

C# 类 SimpleStruct 使用 public 可读属性作为 MATLAB 的输入,并在编组时使用 public 构造函数作为 MATLAB 的输出。

当此类作为输入传递给 MATLAB 函数时,它会生成一个 MATLAB 结构体,其中包含字段 Field1 和 Field2,它们被定义为 public 可读属性。当从 MATLAB 传递具有字段名称 Field1 和 Field2 的 MATLAB 结构时,它将用作目标 .NET 类型(分别为 string 和 double),因为它具有带有输入参数 Field1 和 Field2 的构造函数。

public class SimpleStructExample
 {
     private string f1;
     private double f2; 
     
     public SimpleStruct(string Field1, double Field2)
     {
         f1 = Field1;
         f2 = Field2;    
     }

     public string Field1
     {
         get
         {
             return f1;
         }          
     }

     public double Field2
     {
         get
         {
             return f2;
         }
     }
 }

MATLAB 函数 sortstudents 接受 student 结构体数组并按学生分数升序对输入数组进行排序。struct 数组中的每个元素代表有关 student 的不同信息。

提供了 C# 接口 StudentSorter 和方法 sortstudents 来显示 C# 中的等效功能。

您的 .NET 结构体和类必须遵守特定要求,这些要求既基于作用域级别(例如,字段和属性,而不是构造函数),也基于您是将 .NET 类型编组到 MATLAB 结构体,还是反向编组。有关详细信息,请参阅使用 .NET 结构和类。

function sorted = sortstudents(unsorted)
% Receive a vector of students as input
% Get scores of all the students
scores = {unsorted.score};
% Convert the cell array containing scores into a numeric array or doubles
scores = cell2mat(scores);
% Sort the scores array
[s i] = sort(scores);
% Sort the students array based on the sorted scores array
sorted = unsorted(i);

注意

尽管此示例仅使用输入结构体的 scores 字段,但您也可以以类似的方式使用 name 和 grade 字段。

.NET 接口 StudentSorter 与方法 sortstudents 使用先前定义的 .NET Student 结构进行输入和输出。在 .NET 中编组用于输入和输出的结构时,Student 结构或类必须包含在 MWStructureList 属性中。有关此自定义属性的详细信息,请参阅位于 $MPS_INSTALL/client 的 .NET API 文档。

public interface StudentSorter {
    [MWStructureList(typeof(Student))]
    Student[] sortstudents(Student[] students);
}
using System;
using System.Net;
using MathWorks.MATLAB.ProductionServer.Client;

namespace MPS
{
    public interface StudentSorter
    {
        [MWStructureList(typeof(Student))]
        Student[] sortstudents(Student[] students);
    }

    class ClientExample
    {
        static void Main(string[] args)
        {
            MWClient client = null;

            try
            {
                client = new MWHttpClient();
                StudentSorter mpsexample = 
                    client.CreateProxy(new Uri("http://test-machine:9910/scoresorter"));

                Student s1 = new Student();
                s1.name = "Tony Miller";
                s1.score = 90;
                s1.grade = "A";

                Student s2 = new Student();
                s2.name = "Ed Plum";
                s2.score = 80;
                s2.grade = "B+";

                Student s3 = new Student();
                s3.name = "Mark Jones";
                s3.score = 85;
                s3.grade = "A-";

                Student[] unsorted = new Student[] { s1, s2, s3 };

                Console.WriteLine("Unsorted list of students :");
                foreach (Student st in unsorted)
                {
                    Console.WriteLine(st);
                }

                Console.WriteLine();
                Console.WriteLine("Sorted list of students :");

                Student[] sorted = mpsexample.sortstudents(unsorted);

                foreach (Student st in sorted)
                {
                    Console.WriteLine(st);
                }
                
            }
            catch (WebException ex)
            {
                HttpWebResponse response = (HttpWebResponse)ex.Response;
                if (response != null)
                {
                    Console.WriteLine("Status code : " + 
                                           response.StatusCode);
                    Console.WriteLine("Status description : " + 
                                    response.StatusDescription);
                }
                else
                {
                    Console.WriteLine("No response received in 
                             WebException with status : " + ex.Status);
                }

            }
            catch (MATLABException ex)
            {
                Console.WriteLine("MATLAB error thrown : ");
                Console.WriteLine(ex.MATLABIdentifier);
                Console.WriteLine(ex.MATLABStackTraceString);
            }
            finally
            {
                if (client != null)
                {
                    client.Dispose();
                }
            }
        }
    }
}

运行该应用程序时,将生成以下输出:

Unsorted list of students :
Tony Miller : A : 90
Ed Plum : B+ : 80
Mark Jones : A- : 85

Sorted list of students :
Ed Plum : B+ : 80
Mark Jones : A- : 85
Tony Miller : A : 90
Press any key to continue . . .

使用属性

除了使用 使用 .NET 结构和类 中描述的技术之外,属性还提供了多种方法来在 .NET 类型和 MATLAB 结构体之间进行编组。

MATLAB Production Server™ 定义的属性 MWStructureList 可以限定在字段、属性、方法或接口级别。

在下面的示例中,MATLAB 函数将包含各种 MATLAB cell 数据类型的 struct 数组(向量)作为输入,并返回包含输入 cell 的修改版本的 struct 数组(向量)作为输出。

function outCell = modifyinput(inCell)

使用两种 .NET 结构类型定义 cell 数组:

public struct Struct1{
    ...
    ...
}
public struct Struct2{
    ...
    ...
}

如果不使用 MWStructureList 属性,接口 StructExample 中的 C# 方法签名如下:

public interface StructExample
{
    public object[] modifyinput(object[] cellArrayWithStructs);
}

请注意,此签名并未提供有关 cellArrayWithStructs 在运行时包含的结构体类型的信息。但是,通过使用 MWStructureList 属性,您可以直接在方法签名中定义这些类型:

public interface StructExample
{
    [MWStructureList(typeof(Struct1), typeof(Struct2))]
    public object[] modifyinput(object[] cellArrayWithStructs);
}

MWStructureList 属性的范围可以为:

方法属性

在此示例中,属性 MWStructureList 用作方法属性,用于编组输入和输出类型。

public interface StructExample
{
    [MWStructureList(typeof(Struct1), typeof(Struct2))]
    public object[] modifyinput(object[] cellArrayWithStructs);
}

在此示例中,结构类型 Struct1 和 Struct2 未向方法 modifyinputNew 公开,因为 modifyinputNew 是单独的方法签名

public interface StructExample
{
    [MWStructureList(typeof(Struct1), typeof(Struct2))]
    public object[] modifyinput(object[] cellArrayWithStructs);
    public object[] modifyinputNew(object[] cellArrayWithStructs);
}

接口属性

当在接口级别使用时,属性由接口的所有方法共享。

在下面的示例中,modifyinput 和 modifyinputNew 方法共享接口属性 MWStructureList,因为该属性是在 interface 声明之前定义的。

[MWStructureList(typeof(Struct1), typeof(Struct2))] 
public interface StructExample
{     
    public object[] modifyinput(object[] cellArrayWithStructs);
    public object[] modifyinputNew(object[] cellArrayWithStructs);
}

字段和属性特性

使用 public 字段或 public 属性编写接口。

您可以使用字段和属性以三种方式表示这种类型的 .NET struct:

  • 在字段上:

    使用 public 字段和 MWStructureList 属性:

    public struct StructWithinStruct
    {
        [MWStructureList(typeof(Struct1), typeof(Struct2))]
        public object[] cellArrayWithStructs;
    }
    
  • 在属性处,对于 get 和 set 方法:

    使用 public 属性和 MWStructureList 特性:

    public struct StructWithinStruct
    {     
        private object[] arr;
        
        [MWStructureList(typeof(Struct1), typeof(Struct2))]
        public object[] cellArrayWithStructs
        {
            get
            {
                return arr;
            }
    
            set
            {
                arr = value;
            } 
        }
    }
    
  • 在属性处,对于 get 或 set 方法,取决于此结构是否将用作 MATLAB 的输入或 MATLAB 的输出:

    public struct StructWithinStruct
    {     
        private object[] arr;     
        
        public object[] cellArrayWithStructs
        {
            [MWStructureList(typeof(Struct1), typeof(Struct2))]
            get
            {
                return arr;
            }
            
            [MWStructureList(typeof(Struct1), typeof(Struct2))]
            set
            {
                arr = value;
            } 
        }
    }
    

    注意

    最后两个示例显示了属性 (property) 使用的特性 (attributes),产生相同的结果。

另请参阅

主题