有什么办法把模型编译成2进制执行仍然可以获取中间变量的方法吗,如果不把中间变量放进outport

27 次阅读

本文最后更新于 2026年8月22日。

ai可以写c脚本把模型生成的c代码利用matlab编译成mexw64文件仿真,但改动较多,麻烦

可以。将模型编译成二进制的动态链接库(DLL)进行调用,同时获取内部中间变量,这是通过“代码生成 + CAPI 接口”或“信号线标定”等专业方法可以实现的,而非将变量都连到 Outport 模块。

下面核心思路和方案:

核心思路:改变变量的“存储类”

编译成二进制后,想要在外部读取内部信号,关键不在于如何“输出”它,而在于如何在代码生成阶段就为这个信号在内存中预留一个可访问的、命名清晰的变量。这主要是通过修改信号或参数在生成代码中的“存储类 (Storage Class)”来实现的。

常用的方法有以下几种:

  1. 作为全局变量 (Global Variable):将关键的内部信号或模块参数设置为 SimulinkGlobalExportedGlobal 存储类。这样,在生成的 C 代码中,它们会成为真正的全局变量,外部程序可以通过 DLL 导出符号直接访问。此方法最为直接,适用于需要频繁读写的关键变量。
  2. 设置为 Test Point:在 Simulink 模型中,右键点击你关心的信号线,选择 Properties,并勾选 Test point。这会告诉代码生成器,即使该信号在模型中只是中间节点,也必须在生成的代码中为其生成一个独立的、可观测的变量,防止优化掉。之后,可以通过 CAPI 接口或内存映射来访问。
  3. 使用 CAPI (Code API) 接口:这是比较专业和系统级的方法。在编译(尤其是生成DLL)时,激活 CAPI 选项(通常在 Code Generation -> Interface 中,选择 CAPI 并勾选 signals, parameters 等)。这样,编译出的DLL会包含一个内存地址映射表。外部程序可以通过调用特定的导出函数,获取这个映射表,从而根据信号的名称,动态地找到并读写其内存地址。

推荐方案与实施路径

综合来看,最通用的方案是将模型编译为带有 CAPI 接口信息的 DLL,然后由主程序(如 Python、C++)加载并调用。

实施路径(基于CAPI生成DLL)

  1. 准备模型:在 Simulink 模型中,对你关心的内部信号线,建议设置其为 Test Point。这能确保它们一定在生成的代码中“存活”下来,并且拥有独立的变量名。
  2. 配置代码生成
    • 打开“Configuration Parameters”。
    • Code Generation 页面,将 System target file 设置为 ert_shrlib.tlc(或 ert.tlc),这用于生成可重用的嵌入式C代码。
    • 进入 Code Generation -> Interface 子页面。
    • Code interface packaging 下拉菜单中,选择 CAPIReusable function关键一步:在下方的复选框中,勾选 signalsparametersstatesroot-level I/O
  3. 编译生成DLL:点击 Build 按钮进行编译。完成后,你会得到 .dll.lib(导入库)以及一系列 .c/.h 文件。
  4. 在外部程序中调用
    • 外部程序(如 Python 的 ctypes 库)加载此 DLL。
    • 调用导出的初始化函数(如 model_initialize())和步进函数(如 model_step())来执行模型。
    • 获取内部变量:通过调用生成的辅助函数(如专利中提到的 getDataAddrMap())或直接读取结构体(如 MODEL_NAME_U 为输入,MODEL_NAME_Y 为输出,其他全局变量在头文件中定义),来访问内存中的变量值。

另一种方法:手动编写访问接口

如果不想使用 CAPI,也可以在 Simulink 模型的 Model Workspace 中,将你关心的中间变量定义为 Simulink.ParameterSimulink.Signal 对象,并显式设置其 StorageClassExportedGlobal。这样,编译后它们会变成C文件中的全局变量,你可以在外部程序中通过 extern 声明直接访问。


总结一下,最关键的操作是在配置代码生成时启用 CAPI 接口并为信号设置 Test Point。这能确保中间变量在二进制代码中“有名有姓”,并可被外部程序通过内存地址找到。