从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 / 代码生成场景下的实际表现
结合你现在的需求:
-
在 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 头文件"挡在"仿真构建之外。