实现类型安全接口并集成到 .NET 应用程序中
此示例说明如何实现类型安全接口并将其集成到 .NET 应用程序中。
类型安全接口允许您直接使用熟悉的本机数据类型,而不必使用 MWArray API。向 .NET 程序集添加类型安全接口会创建一组额外的方法,用于接受和返回本机 .NET 类型。
编写并测试您的 MATLAB 代码
创建 MATLAB® 程序,然后在实现类型安全接口之前测试代码。MATLAB 程序中的函数必须与本机 .NET 接口中的声明相匹配。
对于此示例,将以下代码保存为 multiply.m。该函数返回输入 x 和 y 的乘积。
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# 源代码作为界面。
打开 Microsoft® Visual Studio® 并创建一个名为
IMultiply的新 Class Library (.NET Framework) 工程。在解决方案资源管理器窗口中,将
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 函数完全匹配。
所有方法都有两个输入和一个输出(以匹配 MATLAB
multiply函数),但参数数据类型各不相同。转到 Build,然后转到 Configuration Manager,并将平台从 Any CPU 更改为 x64。
使用 Microsoft Visual Studio 构建工程。
在构建文件夹中生成文件
IMultiply.dll。
此示例假设您的程序集仅包含 IMultiply。实际上,类型安全接口更有可能已经是已编译程序集的一部分。甚至可以在编写 MATLAB 函数之前编译汇编。
使用 .NET 程序集编译器创建 .NET 程序集
在 R2025a 之前的版本中,您可以使用 .NET 程序集编译器应用程序生成与 .NET 程序集对应的类型安全接口。或者,如果您想使用编程方法从 MATLAB 命令行窗口创建 .NET 程序集,请参阅 使用 compiler.build.dotNETAssembly 创建 .NET 程序集。
创建一个 .NET 组件编译器工程,从类型列表中选择 .NET 程序集。
指定以下值:
字段 值 库名称 Multiply类名 Arithmetic要编译的文件 multiply.m展开其他运行时设置部分。
在类型安全的 API 部分中,执行以下操作:
选择启用类型安全的 API。
在接口程序集字段中,指定您构建的类型安全接口程序集
IMultiply.dll的位置。从 .NET 接口下拉框中选择
IMultiply接口。将命名空间字段留空。
在包装的类字段中指定
Arithmetic类。
点击打包按钮来构建工程。
使用 compiler.build.dotNETAssembly 创建 .NET 程序集
作为 .NET 程序集编译器的替代方案,您可以通过以下步骤使用程序化方法生成类型安全的接口。如果您已经使用 .NET 程序集编译器创建了组件,请参阅将 .NET 程序集集成到 .NET 应用程序中。
使用
compiler.build.dotNETAssembly函数编译 .NET 程序集。使用名称-值参量指定程序集名称和类名。compiler.build.dotNETAssembly('multiply.m', ... 'AssemblyName','Multiply', ... 'ClassName','Arithmetic');
导航到生成的
MultiplydotNETAssembly文件夹。使用 MATLAB 中的
ntswrap命令生成类型安全接口:ntswrap('-c','Multiply.Arithmetic', ... '-a','IMultiply.dll', ... '-i','IMultiply');
并非所有参量都是互相兼容的。有关所有命令选项的详细信息,请参阅
ntswrap。提示
如果
IMultiply.dll程序集不在当前文件夹中,请指定完整路径。此命令生成程序集
ArithmeticIMultiply.dll,其中包含命名空间Arithmetic中 MATLAB Compiler SDK™ 类MultiplyNative的类型安全 API。
将 .NET 程序集集成到 .NET 应用程序中
创建 .NET 程序集后,您可以将其集成到任何 .NET 应用程序中。您可以使用此示例 .NET 应用程序代码作为指南来编写您自己的 .NET 应用程序。
按照以下步骤使用 Microsoft Visual Studio 编译 .NET 程序:
打开 Microsoft Visual Studio 并创建一个名为
MultiplyApp的 C# Console App (.NET Framework)。将以下源代码复制到工程中生成的
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; } } }在工程中添加对以下文件的引用。
此引用: 定义: IMultiply.dll.NET 本机类型接口程序集 IMultiplyArithmeticIMultiply.dll生成的类型安全 API MultiplyNative.dll生成的 .NET 程序集 注意
与其他 .NET 部署场景不同,您不需要在服务器程序源代码中引用
MWArray.dll。MWArray数据类型隐藏在ArithmeticIMultiply中类型安全的 API 后面。转到 Build,然后转到 Configuration Manager,并将平台从 Any CPU 更改为 x64。
使用 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出现在输入x和y之前。.NET 接口函数不需要这种排序。输入可能出现在输出之前或之后,或者两者混合在一起。MATLAB Compiler SDK 根据函数名称和参量数量将 .NET 接口函数与公共 MATLAB 函数进行匹配。在
multiply示例中,.NET 接口函数和 MATLAB 函数都必须命名为multiply,并且两个函数必须定义相同数量的参量。输入和输出参量的数量和相对顺序至关重要。
在评估参数顺序时,只考虑类似参数(输入或输出)的顺序,而不管它们出现在参数列表中的什么位置。
接口中的函数的输入可能比其对应的 MATLAB 函数少,但不会多。
参量映射根据参量顺序而不是参量名称进行。
如果指定了函数返回值,则该值算作第一个输出。
您必须使用
out参数来执行多个输出。另外,
ref参数可用于out,因为ref和out是同义词。
MATLAB 不支持函数重载。因此,具有给定名称的函数的所有用户提供的重载都将映射到由 MATLAB Compiler SDK 生成的函数。
看.NET 类型到 MATLAB 类型有关使用类型安全接口管理数据转换的完整指南。
另请参阅
compiler.build.dotNETAssembly | ntswrap