编写可部署的 MATLAB 代码
为了打包和部署 MATLAB® 代码,您的代码必须遵循某些准则以避免错误。
打包时可接受的文件类型
使用部署 App 进行打包的有效和无效文件类型如下。
| 目标应用程序 | 有效文件类型 | 无效的文件类型 |
|---|---|---|
独立应用程序 | MATLAB MEX 文件、MATLAB 脚本、MATLAB 函数和 MATLAB 类文件。这些文件必须有一个单一的入口点。 | 受保护的函数文件( |
C/C++ 共享库、.NET 程序集、Java 类、Python® 包和 COM 组件 | MATLAB MEX 文件、MATLAB 函数和 MATLAB 类文件。这些文件必须有一个单一的入口点。 | MATLAB 脚本、受保护的函数文件( |
MATLAB 生产服务器存档 | MATLAB MEX 文件和 MATLAB 函数。这些文件必须有一个单一的入口点。 | MATLAB 脚本、MATLAB 类文件、受保护的函数文件( |
您可以将其他类型的文件添加到打包的代码存档中,例如数据文件。有关详细信息,请参阅在打包的应用程序中包含和访问文件。
打包的应用程序在运行时不处理 MATLAB 文件
编译器保护您的代码免遭未经授权的更改。可部署的 MATLAB 文件在编译时被暂停或冻结。这并不意味着您不能部署灵活的应用程序- 而是意味着您在设计应用程序时必须考虑灵活性。例如,如果您希望最终用户能够在两种不同的方法之间进行选择,则可部署存档中必须提供这两种方法。
MATLAB Runtime 仅适用于构建可部署存档时加密的 MATLAB 代码。任何动态生成新 MATLAB 代码的函数或过程都无法对抗 MATLAB Runtime。
一些 MATLAB 工具箱(例如 Deep Learning Toolbox™ 产品)可以动态生成 MATLAB 代码。由于 MATLAB Runtime 仅执行加密的 MATLAB 文件,而 Deep Learning Toolbox 生成未加密的 MATLAB 文件,因此 Deep Learning Toolbox 中的某些函数无法部署。
同样,需要检查 MATLAB 函数文件内容的函数也无法部署。例如,HELP 是动态的,在部署模式下不可用。如果您为 LOADLIBRARY 提供了 MATLAB 函数原型,则可以在部署模式下使用 LOADLIBRARY。
不要编译生成 MATLAB 代码的函数并尝试部署它,而是执行以下任务:
在 MATLAB 中运行代码一次以获取生成的函数。
打包 MATLAB 代码并包含生成的函数。
提示
使用 EVAL 或 FEVAL 的另一种替代方法是使用匿名函数句柄。
如果您需要创建用于动态运行时处理 MATLAB 代码的能力,您的最终用户必须安装 MATLAB 副本。
获取您想要部署的工具箱功能的适当许可证
您必须拥有用于创建可部署 MathWorks® 代码的工具箱的有效 MATLAB 许可证。您的最终用户不需要任何许可证即可运行打包的工具箱代码。
使用 isdeployed 函数执行特定于部署的代码路径
isdeployed 函数允许您指定 MATLAB 代码的哪部分可部署,哪部分不可部署。这样的规范可以最大限度地减少编译错误,并有助于创建更高效、更易于维护的代码。
例如,您会发现在编写 addpath 时不可避免地需要使用 startup.m。使用 ismcc 和 isdeployed,您可以指定何时打包和执行什么。
if ~(ismcc || isdeployed) addpath(mypath); end
不要依赖更改目录或路径来控制 MATLAB 文件的执行
一般来说,良好的编程实践建议不要在代码中动态地重定向程序搜索路径。许多开发人员容易出现这种行为,因为它模仿了他们通常在命令行上执行的操作。然而,这可能会在部署代码时导致问题。
例如,在部署的应用程序中,MATLAB 和 Java 路径是固定的,不能改变。因此,任何尝试更改这些路径(使用 cd 命令或 addpath 命令)都会失败。
如果您发现无法避免在 MATLAB 代码中放置 addpath 调用,请使用 ismcc 和 isdeployed。有关详细信息,请参阅使用 isdeployed 函数执行特定于部署的代码路径。
逐步重构依赖于不可部署函数的应用程序
随着时间的推移,重构、简化和模块化包含使用 isdeployed 不可编译或不可部署函数 MATLAB 代码。您的最终目标是“优雅降级”不可部署的代码。换句话说,代码必须给最终用户带来尽可能少的部署障碍,直到实际上消除为止。
将代码划分为设计时代码部分和运行时代码部分:
设计时代码是当前正在发展的代码。几乎所有代码都会经历不断重写、调试和优化的阶段。在某些工具箱中,例如 Deep Learning Toolbox 产品,代码会经历一段时间的自我训练,因为它会对各种数据排列和模式做出反应。此类代码几乎从未被设计用于部署。
另一方面,运行时代码已经固化或变得稳定 - 它处于完成状态并准备好由最终用户部署。
考虑为不打算部署的代码或调用不可部署代码的代码创建单独的目录。
不要创建或使用非常量静态状态变量
避免使用以下内容:
MATLAB 代码中的全局变量
MEX 文件中的静态变量
Java 代码中的静态变量
这些变量的状态是持久的,并与流程中的所有内容共享。
部署应用程序时,使用持久变量可能会导致问题,因为 MATLAB Runtime 进程在单个线程中运行。您不能将多个非常量静态变量加载到同一个进程中。此外,这些静态变量在多线程应用程序中不能很好地工作。
当针对打包的 MATLAB 代码进行编程时,您应该知道每个新类的实例都会创建一个 MATLAB Runtime 实例。如果使用不同的变量名再次实例化同一个类,它将附加到由同一个类的前一个实例创建的 MATLAB Runtime 实例。简而言之,如果一个程序集包含 n 个唯一类,则将创建最多 n 个 MATLAB Runtime 实例,每个实例对应其中一个类的一个或多个实例。
如果必须使用静态变量,请将它们绑定到实例。例如,在 Java 类中定义实例变量比将变量定义为 static 变量更好。