从C到Simulink:什么是MATLAB_MEX_FILE 宏,如何阻挡STM32 HAL 头文件

从C到Simulink:什么是MATLAB_MEX_FILE 宏,如何阻挡STM32 HAL 头文件


一、MATLAB_MEX_FILE 是在哪定义的?

结论先说在前面:

  • MATLAB_MEX_FILE 不是你在某个 .h 文件里写的
  • 它是:
    • 当你用 mex 命令编译 MEX 文件时,编译命令行里自动加上的一个宏;
    • 当 Simulink 仿真模型调用 C/C++ 代码(比如 C MEX S-Function、Legacy Code Tool 引入的代码)时,Simulink 会使用 mex 来编译这些代码,此时编译命令行里也会自动定义这个宏。
  • 在真正生成嵌入式代码(比如生成 STM32 工程)时,这个宏是不会被定义的。
    MathWorks 的 C MEX S-Function 文档和工程实践中都提到:
  • 在为 MEX DLL 编译 S-function 源码时,会定义 MATLAB_MEX_FILE 宏【turn0search11】【turn0search13】。
    也就是说:
  • 只要你的 C 代码是"为了在 Simulink 仿真里跑"而被 mex 编译成 .mex* 动态库,
  • 那么编译命令里就有 -DMATLAB_MEX_FILE
  • 你的代码里就可以用:
c 复制代码
#ifdef MATLAB_MEX_FILE
// 仿真环境(宿主机)的代码
#else
// 真实目标环境(比如 STM32)的代码
#endif

二、为什么你在源代码里搜不到这个宏?

因为:

  • 它不在任何 .h/.c 文件里,
  • 而是编译命令行里的选项(-D 宏)。
    你可以简单理解成:
  • 调用类似:
bash 复制代码
mex -v my_driver.c ...

时,真正交给编译器的大致是:

bash 复制代码
gcc -DMATLAB_MEX_FILE ... my_driver.c ...

所以:

  • mex 命令负责自动加上这个宏;
  • 你的源代码只要"检测"它,而不要"定义"它。

三、如何自己验证这个宏确实被定义了?

如果你不放心,可以写一个很小的测试文件,看看 MATLAB_MEX_FILE 在什么时候有定义。

1)写一个 test.c

c 复制代码
#include <stdio.h>
int main(void)
{
#ifdef MATLAB_MEX_FILE
    printf("MATLAB_MEX_FILE is defined.\n");
#else
    printf("MATLAB_MEX_FILE is NOT defined.\n");
#endif
    return 0;
}

2)用普通编译器编译(比如 gcc/clang)

命令行执行(Windows 下用 MinGW、Linux/Mac 上直接 gcc):

bash 复制代码
gcc test.c -o test
./test

你会看到输出:

text 复制代码
MATLAB_MEX_FILE is NOT defined.

因为这里没用 mex,编译命令里没有 -DMATLAB_MEX_FILE

3)用 mex 编译(在 MATLAB 里执行)

matlab 复制代码
mex test.c
!test

这次输出会是:

text 复制代码
MATLAB_MEX_FILE is defined.

这就是最直接的证据:

  • mex 编译时,MATLAB_MEX_FILE 宏是被定义的;
  • 普通 C 编译时,没有这个宏。
    同理:
  • Simulink 仿真构建时,也是通过内部调用 mex 编译 S-Function/Legacy Code 代码,所以这个宏同样存在;
  • 生成嵌入式代码时,走的是 Embedded Coder/RTW 的构建过程,不会再定义 MATLAB_MEX_FILE

结合你现在的需求:

  • 在 Simulink 里跑模型(包含 C MEX S-Function/Legacy Code):

    • 编译器 = 宿主机编译器(MSVC/MinGW/Clang)

    • 编译方式 = mex

    • 宏情况:MATLAB_MEX_FILE 已定义

    • 所以代码走:

      c 复制代码
      #ifdef MATLAB_MEX_FILE
      // 仿真分支:不引入 stm32xxxx_hal.h,或者使用 mock
      #endif
  • 在 Simulink 里"生成代码"给 STM32 用:

    • 编译器 = 交叉编译器(ARM GCC/Keil/IAR 等)

    • 构建方式 = Embedded Coder 的 makefile/project 生成

    • 宏情况:MATLAB_MEX_FILE 不会被定义

    • 所以代码走:

      c 复制代码
      #ifndef MATLAB_MEX_FILE
      // 真实目标分支:正常包含 stm32xxxx_hal.h
      #include "stm32f4xx_hal.h"
      #endif

所以,之前建议你用:

c 复制代码
#ifndef MATLAB_MEX_FILE
    #include "stm32xxxx_hal.h"
#else
    // 仿真分支的 mock 定义
#endif

是安全可行的。

五、如果你好奇,想看 mex 究竟传了什么编译参数

在 MATLAB 里可以通过 mex -v 看到详细的编译命令。

例如:

matlab 复制代码
mex -v my_driver.c

命令行输出里你会看到类似:

text 复制代码
... -DMATLAB_MEX_FILE ... my_driver.c

其中:

  • -D 就是"定义宏"的选项;
  • MATLAB_MEX_FILE 就是宏名;
  • 后面没有 =xxx,说明它被定义为 1,相当于:
c 复制代码
#define MATLAB_MEX_FILE 1

六、小结

  • MATLAB_MEX_FILE 这个宏:
    • 不是在你代码里定义的;
    • 是 MATLAB 的 mex 工具在编译 MEX 文件时,自动加在命令行里的宏定义(-DMATLAB_MEX_FILE)【turn0search11】【turn0search13】;
    • Simulink 仿真模型在构建 C MEX S-Function / Legacy Code 时,也会通过 mex 编译,因此这个宏同样存在;
    • 真正生成嵌入式代码时(比如生成 STM32 工程),这个宏不会被定义。
      所以,你可以安心在自定义驱动代码里用:
c 复制代码
#ifndef MATLAB_MEX_FILE
    // 目标环境(STM32)
    #include "stm32xxxx_hal.h"
#else
    // 仿真环境(PC)
    // mock 定义/不引入 HAL
#endif

这样就能干净地把 STM32 HAL 头文件"挡在"仿真构建之外。

相关推荐
我爱C编程2 小时前
基于SARSA强化学习的迷宫路线规划matlab仿真
matlab·强化学习·sarsa·迷宫路线规划
Darken032 小时前
基于STM32---编码器测速(利用GPIO模拟脉冲信号)
人工智能·stm32·串口助手·gpio模拟编码器
会员果汁2 小时前
算法-并查集-C
c语言·开发语言·算法
机器学习之心3 小时前
BO-CNN-BiLSTM贝叶斯优化卷积双向长短期记忆神经网络多输入多输出预测,MATLAB代码
神经网络·matlab·cnn·bo-cnn-bilstm
脏脏a3 小时前
链式存储范式下的二叉树:基础操作实现解析
c语言·数据结构·算法·二叉树
youcans_4 小时前
【STM32-MBD】(9)Simulink 模型开发之上位机显示波形
stm32·单片机·嵌入式硬件·上位机·simulink
兆龙电子单片机设计4 小时前
【STM32项目开源】STM32单片机智能家居语音控制系统
stm32·单片机·物联网·开源·毕业设计·智能家居
d111111111d4 小时前
STM32的ADC是什么,其转换精度通常有那些选项?
笔记·stm32·单片机·嵌入式硬件·学习
小刘爱玩单片机4 小时前
【stm32简单外设篇】- 红外避障 / 红外循迹模块
c语言·stm32·单片机·嵌入式硬件