主要内容

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

实现类型安全接口并集成到 .NET 应用程序中

此示例说明如何实现类型安全接口并将其集成到 .NET 应用程序中。

类型安全接口允许您直接使用熟悉的本机数据类型,而不必使用 MWArray API。向 .NET 程序集添加类型安全接口会创建一组额外的方法,用于接受和返回本机 .NET 类型。

编写并测试您的 MATLAB 代码

创建 MATLAB® 程序,然后在实现类型安全接口之前测试代码。MATLAB 程序中的函数必须与本机 .NET 接口中的声明相匹配。

对于此示例,将以下代码保存为 multiply.m。该函数返回输入 xy 的乘积。

function z = multiply(x,y)
z = x * y;

在 MATLAB 命令提示符下测试该函数。

multiply([1 4 7; 2 5 8; 3 6 9],[1 4 7; 2 5 8; 3 6 9])
 ans =

    30    66   102
    36    81   126
    42    96   150

实现类型安全接口

编写并测试 MATLAB 代码后,使用 C# 或 Visual Basic® 开发 .NET 类型安全接口。此示例使用提供的 C# 源代码作为界面。

  1. 打开 Microsoft® Visual Studio® 并创建一个名为 IMultiply 的新 Class Library (.NET Framework) 工程。

  2. 在解决方案资源管理器窗口中,将 Class1.cs 文件重命名为 IMultiply.cs。在此文件中,您可以为访问组件的类型安全接口编写源代码。

    在此示例中,IMultiply 接口用 C# 编写,并指定了 multiply 的三个重载:

    using System;
    
    public interface IMultiply
    {
        // Scalar multiplication
        System.Double multiply(System.Double x, System.Double y);
    
        // Multiply vector by a scalar, return a vector
        System.Double[] multiply(System.Double[] x, System.Double y);
    
        // Matrix multiplication
        System.Double[,] multiply(System.Double[,] x, System.Double[,] y);
    }

    接口中的每个方法必须与部署的 MATLAB 函数完全匹配。

    所有方法都有两个输入和一个输出(以匹配 MATLABmultiply 函数),但参数数据类型各不相同。

  3. 转到 Build,然后转到 Configuration Manager,并将平台从 Any CPU 更改为 x64

  4. 使用 Microsoft Visual Studio 构建工程。

    在构建文件夹中生成文件 IMultiply.dll

此示例假设您的程序集仅包含 IMultiply。实际上,类型安全接口更有可能已经是已编译程序集的一部分。甚至可以在编写 MATLAB 函数之前编译汇编。

使用 .NET 程序集编译器创建 .NET 程序集

使用 .NET 程序集编译器通过 .NET 程序集生成类型安全的接口。或者,如果您想使用编程方法从 MATLAB 命令行窗口创建 .NET 程序集,请参阅使用 compiler.build.dotNETAssembly 创建 .NET 程序集

  1. 创建一个 .NET 组件编译器工程,从类型列表中选择 .NET 程序集

  2. 指定以下值:

    字段
    库名称Multiply
    类名Arithmetic
    要编译的文件multiply.m

  3. 展开其他运行时设置部分。

  4. 类型安全的 API 部分中,执行以下操作:

    1. 选择启用类型安全的 API

    2. 接口程序集字段中,指定您构建的类型安全接口程序集 IMultiply.dll 的位置。

    3. .NET 接口下拉框中选择 IMultiply 接口。

    4. 命名空间字段留空。

    5. 包装的类字段中指定 Arithmetic 类。

  5. 点击打包按钮来构建工程。

使用 compiler.build.dotNETAssembly 创建 .NET 程序集

作为 .NET 程序集编译器的替代方案,您可以通过以下步骤使用程序化方法生成类型安全的接口。如果您已经使用 .NET 程序集编译器创建了组件,请参阅将 .NET 程序集集成到 .NET 应用程序中

  1. 使用 compiler.build.dotNETAssembly 函数编译 .NET 程序集。使用名称-值参量指定程序集名称和类名。

    compiler.build.dotNETAssembly('multiply.m', ...
        'AssemblyName','Multiply', ...
        'ClassName','Arithmetic');
    
  2. 导航到生成的 MultiplydotNETAssembly 文件夹。

  3. 使用 MATLAB 中的 ntswrap 命令生成类型安全接口:

    ntswrap('-c','Multiply.Arithmetic', ...
            '-a','IMultiply.dll', ...
            '-i','IMultiply');

    并非所有参量都是互相兼容的。有关所有命令选项的详细信息,请参阅 ntswrap

    提示

    如果 IMultiply.dll 程序集不在当前文件夹中,请指定完整路径。

    此命令生成程序集 ArithmeticIMultiply.dll,其中包含命名空间 ArithmeticMATLAB Compiler SDK™MultiplyNative 的类型安全 API。

将 .NET 程序集集成到 .NET 应用程序中

创建 .NET 程序集后,您可以将其集成到任何 .NET 应用程序中。您可以使用此示例 .NET 应用程序代码作为指南来编写您自己的 .NET 应用程序。

按照以下步骤使用 Microsoft Visual Studio 编译 .NET 程序:

  1. 打开 Microsoft Visual Studio 并创建一个名为 MultiplyApp 的 C# Console App (.NET Framework)

  2. 将以下源代码复制到工程中生成的 Program.cs 中:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace MultiplyApp
    {
        class Program
        {
            delegate String VectorToString<T>(IEnumerable<T> v);
            delegate IEnumerable<String> MatrixToString<T>(T[,] m);
    
            static void Main(string[] args)
            {
                Console.WriteLine("\nStarting application...\n");
                
                //Create an instance of the Type-safe API
                IMultiply m = new ArithmeticIMultiply();
                
                // Scalar multiplication
                double x = 17, y = 3.14159;
                double z = m.multiply(x, y);
                System.Console.WriteLine("{0} * {1} = {2}\n", x, y, z);
    
                // Vector times scalar
                double[] v = new double[] { 2.5, 81, 64 };
                double s = 11;
                double[] d = m.multiply(v, s);
    
                VectorToString<double> vec2str = (vec =>
                  vec.Select(n => n.ToString()).Aggregate((str, next) => str + " " + next));
    
                System.Console.WriteLine("[ {0} ] * {1} = [ {2} ]\n",
                    vec2str(v), s, vec2str(d));
    
                // Matrix multiplication
                double[,] magic = new double[,]{  // 3x3 magic square
                         { 8, 1, 6 },
                         { 3, 5, 7 },
                         { 4, 9, 2 } };
                double[,] squareSquared = m.multiply(magic, magic);
    
                MatrixToString<double> mat2str = mat =>
                    mat.EnumerateRows<double>().Select(r => vec2str(r));
    
                PrintParallel(mat2str(magic), " * ".Select(c => c.ToString()),
                              mat2str(magic), " = ".Select(c => c.ToString()),
                              mat2str(squareSquared));
    
                Console.WriteLine("\nClosing application...");
            }
    
            public static void PrintParallel<T>(params IEnumerable<T>[] sources)
            {
                int max = sources.Select(s => s.Count()).Max();
                for (int i = 0; i < max; i++)
                {
                    foreach (var src in sources)
                        System.Console.Write("{0} ", src.ElementAt(i));
                    System.Console.WriteLine();
                }
            }
        }
        public static class ArrayExtensions
        {
            public static IEnumerable<IEnumerable<T>> EnumerateRows<T>(this Array a)
            {
                return Enumerable.Range(0, a.GetLength(1)).Select(row =>
                    a.ToIEnumerable<T>().Skip(row * a.GetLength(0)).Take(a.GetLength(0)));
            }
    
            public static IEnumerable<T> ToIEnumerable<T>(this Array a)
            {
                foreach (var item in a)
                    yield return (T)item;
            }
    
        }
    }
    
  3. 在工程中添加对以下文件的引用。

    此引用:定义:
    IMultiply.dll.NET 本机类型接口程序集 IMultiply
    ArithmeticIMultiply.dll生成的类型安全 API
    MultiplyNative.dll生成的 .NET 程序集

    注意

    与其他 .NET 部署场景不同,您不需要在服务器程序源代码中引用 MWArray.dllMWArray 数据类型隐藏在 ArithmeticIMultiply 中类型安全的 API 后面。

  4. 转到 Build,然后转到 Configuration Manager,并将平台从 Any CPU 更改为 x64

  5. 使用 Microsoft Visual Studio 编译并运行该程序。

    该程序显示以下输出:

    Starting application...
    
    17 * 3.14159 = 53.40703
    
    [ 2.5 81 64 ] * 11 = [ 27.5 891 704 ]
    
    8 1 6   8 1 6   91 67 67
    3 5 7 * 3 5 7 = 67 91 67
    4 9 2   4 9 2   67 67 91
    
    Closing application...

提示

  • 在 MATLAB 函数中,声明输出出现在输入之前。例如,在 multiply 函数中,输出 z 出现在输入 xy 之前。.NET 接口函数不需要这种排序。输入可能出现在输出之前或之后,或者两者混合在一起。

  • MATLAB Compiler SDK 根据函数名称和参量数量将 .NET 接口函数与公共 MATLAB 函数进行匹配。在 multiply 示例中,.NET 接口函数和 MATLAB 函数都必须命名为 multiply,并且两个函数必须定义相同数量的参量。

  • 输入和输出参量的数量和相对顺序至关重要。

    • 在评估参数顺序时,只考虑类似参数(输入或输出)的顺序,而不管它们出现在参数列表中的什么位置。

    • 接口中的函数的输入可能比其对应的 MATLAB 函数少,但不会多。

  • 参量映射根据参量顺序而不是参量名称进行。

  • 如果指定了函数返回值,则该值算作第一个输出。

  • 您必须使用 out 参数来执行多个输出。

    • 另外,ref 参数可用于 out,因为 refout 是同义词。

  • MATLAB 不支持函数重载。因此,具有给定名称的函数的所有用户提供的重载都将映射到由 MATLAB Compiler SDK 生成的函数。

.NET 类型到 MATLAB 类型有关使用类型安全接口管理数据转换的完整指南。

另请参阅

|

主题