☰
MATLAB 安装 MinGW-w64 支持包:MEX 编译配置与避坑指南
2026/10/13 14:26:17 网站建设 项目流程

简介:这份支持包面向希望利用编译型语言提升MATLAB计算性能的科研与工程人员,适用于MATLAB 2023B/2024A环境。它集成了MinGW-w64编译器,可调用GCC工具链在Windows平台编译C、C++和Fortran代码,并通过MEX接口将原生程序嵌入MATLAB;同时为TrueTime 2.0提供编译器支撑,方便用户在Simulink中建立实时操作系统模型,仿真和验证嵌入式系统的实时行为。压缩包共2000个文件,主体为Python脚本、C/C++头文件及说明文档:896个py脚本多用于工具链配置和自动化处理,787个h与243个hpp头文件负责支撑原生代码与MATLAB的互操作,另有txt说明、Shell脚本及少量C源码辅助安装、链接与调试。包体大小133.84MB,目录包含include、lib、bin、etc、share等标准模块,并附有x86_64-w64-mingw32架构文件与licenses许可,无需额外配置即可解压部署。已有1912人学习下载,适合需要加速数值计算、扩展MEX功能或开展实时仿真研究的MATLAB中高级用户。

1. 编译器装不上时,MATLAB 才真正变成一个黑匣子

我第一次被 MinGW 卡住,是在帮某实验室复现一个图像处理 Demo 时。代码是 C++ 写的,算法逻辑跑在 MATLAB 里,一等函数都写好了,却在mex -setup这一步报“找不到支持的编译器”——那感觉就像 MATLAB 突然变成了黑匣子,你明明装了支持包,系统里也有 gcc,它偏不认。你正在看的这个标题:“MATLAB Support for MinGW-w64 C/C++/Fortran Compiler”,说的就是那个官方支持包,它负责把 MinGW-w64 这套开源编译器接进 MATLAB 的 MEX 编译体系和 Simulink 代码生成链路。这篇文章会把安装、配置、编译命令和坑一条条讲透,让新手能照着走通第一步,让熟手能少踩几个我已经替你踩过的坑。

2. 为什么 MATLAB 自己不内置编译器:MinGW-w64 在编译链里的位置

2.1 MATLAB 需要外部编译器的三个场景

MATLAB 本身是一个解释型环境,但下面三件事必须有外部 C/C++ 编译器:

第一,编译 MEX 文件,也就是用 C/C++ 写算法核心、在 MATLAB 里直接调用,这是性能敏感型任务最常见的落地方式。第二,Simulink 生成代码,无论是嵌入式代码还是桌面级 S-Function,Simulink Coder 都要把模型编译成可执行文件或静态库。第三,通过loadlibrary调用外部 DLL,当你手上只有 C 接口的动态库时,MATLAB 需要一套编译器配套的 SDK 头文件和链接器来生成接口定义。

这三个场景里,编译器不是可选项,是硬依赖。没有编译器,你的 MATLAB 就只能做一个计算器加绘图工具,算法落地寸步难行。

2.2 MinGW-w64 是什么,它和 GCC、TDM-GCC 什么关系

MinGW-w64 是 GCC 在 Windows 下的移植发行版,提供gcc、g++、gfortran三套前端,编译产物是 Windows 原生可执行的二进制,不依赖额外的 POSIX 模拟层。这是它和 Cygwin 最大的区别:MinGW 生成的程序直接在 Windows 的进程模型下运行,加载 msvcrt.dll 或 ucrtbase.dll,而不是模拟 Linux 运行时。

你可能会在论坛里看到 TDM-GCC 这个名字,它也是 MinGW-w64 的一个发行分支。区别在打包方式:TDM-GCC 做的是一键集成包,自带工具链协调版本;而 MATLAB 官方支持包自带的是与 MATLAB 版本匹配的 MinGW-w64 分支。我建议你优先用支持包自带的版本,因为它经过 MATLAB 内部测试,配置注册表项齐全;手动装 TDM-GCC 再手动配置,容易在版本检查上翻车。

2.3 支持包其实做了三件事

安装支持包之后,系统里并不只是多了一个编译器,它实际完成了三个动作:

第一,释放一套完整的 MinGW-w64 工具链到 MATLAB 的 SupportPackages 目录下,包括gcc、g++、gfortran和mingw32-make。第二,在 MATLAB 的编译器注册表里登记这条路径,mex -setup才能枚举到它。第三,安装匹配的头文件和链接配置,让mex知道去哪里找mex.h、libmx.lib、libmex.lib这些 MEX 编译必需的 SDK 文件。

这也是为什么网上有些教程让你自己下 MinGW 然后改系统 PATH,最后mex -setup还是找不到——因为缺了第二步的注册信息。装支持包这个动作,本质上是往 MATLAB 的编译器候选列表里插入一个合法选项。

2.4 为什么不用 MSVC

MSVC 是 Visual Studio 自带的编译器,如果你的 Windows 上有完整 VS 安装,MATLAB 也会自动识别它。但 MSVC 和 MinGW 是两套不同的 ABI,C++ 层面尤其明显:MSVC 用的 STL 实现和 MinGW 用的 libstdc++ 二进制不兼容,用 MSVC 编译的第三方 C++ 库不能直接喂给 MinGW 链接器,反之亦然。MinGW-w64 的优势是免费、无许可证负担、装完即用,对个人开发者尤其友好。后文所有命令默认走 MinGW-w64,如果你必须用 MSVC,编译选项和库路径逻辑大同小异,只是链接器报错风格完全不同。

3. 安装支持包:从 Add-On 安装到 mex -setup 验证

3.1 在 Add-On Explorer 里搜 minGW,装完先别急着编译

打开 MATLAB 主界面,右上角菜单里找“附加功能”,点进去之后选择“获取附加功能”,搜索框里输入MinGW,就能看到MATLAB Support for MinGW-w64 C/C++/Fortran Compiler这个条目,点安装即可。安装器会自动检查你的 MATLAB 版本,然后拉取匹配的编译器分支,整个安装过程可能持续几分钟,取决于网络状况。

这一步有个关键注意事项:安装完成之后,先重启 MATLAB,再执行后面的验证步骤。这不是玄学,是支持包的注册机制在起作用——安装器把编译器信息写进了 MATLAB 启动时才扫描的配置位置,当前会话里不会重新读取。我见过太多人装完就马上敲mex -setup然后报错,到论坛问一圈才发现只是没重启,这个失误属于完全可以避免的踩坑。

3.2 验证编译器是否被识别:mex.getCompilerConfigurations

重启 MATLAB 之后,先跑一条命令确认编译器已经被登记:

>> mex.getCompilerConfigurations('C++', 'Installed') ans = 编译器配置: 名称: MinGW-w64 C/C++ Compiler 版本: 8.1 路径: C:\ProgramData\MATLAB\SupportPackages\R20xx\3P.instrset\mingw_w64.instrset\mingw64

这条命令是只读查询,不会修改任何配置。返回结果里,重点看两个字段:版本号和路径。路径应该指向 SupportPackages 目录下的mingw_w64.instrset\mingw64分支,而不是系统里的其他 MinGW 安装目录。如果这里能列出编译器,说明支持包注册成功,下一步才轮到mex -setup。

mex.getCompilerConfigurations和mex.getCompilerConfigurations('C++', 'Installed')的区别在于:前者返回 MATLAB 可直接调用的所有编译器,包括 C 和 C++;后者明确限定语言和安装状态。查 Fortran 编译器时把参数换成'Fortran'即可,但新版 MATLAB 对 Fortran MEX 的官方支持已经很弱,这条我们放到第 4 章专门说。

3.3 mex -setup 切换默认编译器,并编一个最小样例验证

确认编译器出现在列表里之后,在 MATLAB 命令行执行:

>> mex -setup C++ MEX 配置为使用 'MinGW-w64 C/C++ Compiler' 以编译 C++ 语言代码。 要选择不同的语言,请从以下选项中选择一个命令: mex -setup C mex -setup Fortran

如果机器上同时还装了 MSVC,mex -setup会列出候选列表让你选序号。选择 MinGW 之后,MATLAB 会把默认编译器持久化到用户的配置文件里,之后每次 MATLAB 启动都默认指向它。mex -setup C++只影响 C++ 语言,不会覆盖 C 语言的默认配置;同理mex -setup C只改 C。

配置完成之后,我习惯先编一个最小 MEX 文件,验证整个链路是通的。新建文件check_mex.c:

#include "mex.h" void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double *in, *out; mwSize n; if (nrhs < 1) { mexErrMsgIdAndTxt("check_mex:nrhs", "至少需要 1 个输入"); } n = mxGetNumberOfElements(prhs[0]); plhs[0] = mxCreateDoubleMatrix(1, n, mxREAL); in = mxGetPr(prhs[0]); out = mxGetPr(plhs[0]); for (mwSize i = 0; i < n; ++i) { out[i] = in[i] * 2.0 + 1.0; } }

在命令行执行编译:

>> mex -O check_mex.c >> check_mex([1 2 3 4]) ans = 3 5 7 9

能输出这个结果,说明编译器、SDK、链接器、运行时整条链路都是通的。-O是启用编译器优化,对发布用途的 MEX 文件基本是标配。mexFunction的参数顺序是固定的:nlhs是输出数量,plhs是输出数组指针,nrhs是输入数量,prhs是输入数组指针——写任何 MEX 文件都必须按这个签名来,入口函数名不能改,改了就链接失败。

4. 用支持包编译 C/C++/Fortran 代码:命令、参数和边界

4.1 C 代码编译:从普通函数到 mexFunction 的改造逻辑

C 语言的 MEX 文件改造思路很简单:你已有的 C 函数负责计算,mexFunction负责跟 MATLAB 交换数据。还是以check_mex.c为例,它的核心计算只有一行out[i] = in[i] * 2.0 + 1.0,但在 MATLAB 看来,它就是一个合法的内置函数,支持任意长度的 double 向量输入。

实际工程里,更常见的做法是把你的算法封装在一个普通函数里,然后在mexFunction里调用它。比如:

#include "mex.h" static double my_algorithm(double x) { return x * x + 3.0 * x - 1.0; } void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double val, out; if (nrhs != 1) { mexErrMsgIdAndTxt("calc_mex:nrhs", "需要一个标量输入"); } val = mxGetScalar(prhs[0]); out = my_algorithm(val); plhs[0] = mxCreateDoubleScalar(out); }

编译命令不变:mex -O calc_mex.c。mxGetScalar返回第一个输入元素的值,要求输入是标量或者单元素矩阵;mxCreateDoubleScalar创建 1×1 的 double 输出。这两个函数处理的是 MATLAB 的mxArray结构,跟原生 C 类型之间的转换由 API 自己完成,你不需要关心内存细节,但也不要自己free由 MATLAB 分配的内存。

4.2 C++ 代码编译:标准库和 STL 怎么用

MinGW-w64 在 MATLAB 里编译 C++,最大的便利是可以直接用std::vector、std::string、std::map这些标准库组件,不用担心内存管理。下面这段代码演示了如何把一个 MATLAB 向量搬进std::vector,做累加后返回标量:

#include "mex.h" #include <vector> #include <numeric> void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { if (nrhs != 1) { mexErrMsgIdAndTxt("sum_mex:nrhs", "需要一个输入向量"); } const double *in = mxGetPr(prhs[0]); mwSize n = mxGetNumberOfElements(prhs[0]); std::vector<double> v(in, in + n); double total = std::accumulate(v.begin(), v.end(), 0.0); plhs[0] = mxCreateDoubleScalar(total); }

编译时注意一点:在 MATLAB 命令行里直接敲mex -std=c++17 sum_mex.cpp是不生效的,因为mex命令本身不直接解析-std。需要通过环境变量把参数透传给底层编译器:

>> mex CXXFLAGS="$CXXFLAGS -std=c++17" sum_mex.cpp

这条命令的意思是:在 m ex 默认的 C++ 编译参数基础上追加-std=c++17。$CXXFLAGS是 MATLAB 在调用底层编译器时预设的默认参数集合,你必须保留它,然后追加你的额外要求。同理,如果要加优化等级,可以在命令行加-O,它会映射到底层的-O2,不需要手动指定优化级别。

用 C++ 写 MEX 还有个值得养成的习惯:凡是涉及 C 标准库的头文件,比如<math.h>、<string.h>,在 C++ 代码里尽量改用<cmath>、<cstring>,然后用std::限定。这不只是风格问题,某些平台上 C 头文件和 C++ 头文件的符号导出方式不同,混用可能导致链接阶段出现undefined reference。

4.3 Fortran 编译的边界:官方支持收窄后的替代路线

标题里带 Fortran,确实有历史原因。老版本的 MATLAB 支持直接用mex编译.f或.f90文件,mex -setup Fortran曾经是一个合法选项。但在较新的版本里,MATLAB 对 Fortran MEX 的官方支持已明显收窄,很多版本连mex -setup Fortran都列不出来,即使你在系统里装好了 gfortran 也认不到。

现状是:支持包内含gfortran编译器,它在 MATLAB 生态里的主要价值转向了两个方向——一是 Simulink 的 S-Function Builder,在某些硬件支持包里,Fortran 生成的 S-Function 仍需 gfortran 参与编译;二是通过loadlibrary调用你自己用 Fortran 写的 DLL。第二种是目前更可靠的落地方式:

gfortran -shared -fPIC -o mylib.dll mylib.f90

在 MATLAB 里用loadlibrary加载并调用:

loadlibrary('mylib.dll', 'mylib.h'); result = calllib('mylib', 'myfunc', 3.14); unloadlibrary('mylib');

这条路线的关键坑在于:mylib.h必须声明 Fortran 函数的 C 接口,否则calllib不知道该用什么签名去调。常见做法是在 Fortran 代码里用bind(C)属性导出标准接口,或者提供一个薄薄的 C 包装函数,内部再转发给 Fortran 子程序。如果你确实需要在新版 MATLAB 里编译传统的 Fortran MEX 文件,只能降级到某个老版本 MATLAB,或者改用旧式 Gateway 例程,这里面隐藏的兼容性成本很高,非必要不建议投入。

5. 避坑:支持包装了却用不上,多半是这几个原因

5.1 现象:Add-On 显示已安装,mex -setup 仍然找不到编译器

原因:支持包安装器虽然完成了文件释放,但注册信息是写入 MATLAB 启动时扫描的持久化位置,你当前这个 MATLAB 会话不会自动重读。这也是为什么我第 3 章反复强调装完先重启。

解决:彻底退出 MATLAB(不是关掉图窗,是命令行进程完全结束),重新启动后再执行mex -setup C++。如果重启之后还是找不到,检查支持包是否真的装在了当前 MATLAB 版本对应的 SupportPackages 目录下,有时候你装了 R2021a 的支持包,却拿 R2023b 的 MATLAB 去跑,自然识别不到。

5.2 现象:机器上同时装了 MSVC 和 MinGW,mex 选了 MinGW 却链接失败

原因:如果你用 MSVC 编译过第三方库,产物的.lib文件格式与 MinGW 的lib完全不同。MinGW 的g++链接器只能识别 GCC 风格的静态库和导入库,直接把 MSVC 的.lib传给 MinGW,典型报错是undefined reference to __imp_xxx,或者干脆找不到符号。

解决:第三方库必须用 MinGW 版本重新编译。如果库本身是开源的,用支持包里的mingw32-make重新构建;如果库只提供了 MSVC 编译的预编译二进制,那你只有两条路——换用 MSVC 作为 MATLAB 默认编译器,或者找该库的 MinGW 版本预编译包。混用 ABI 基本无解,别在这个问题上浪费时间。

5.3 现象:mex 编译过程报“编译器版本不匹配”或“该 MATLAB 版本不支持当前编译器”

原因:系统 PATH 里的 gcc 版本与支持包安装的版本冲突,或者你手动安装了系统级 MinGW 覆盖了支持包注册的路径。MATLAB 在调用编译器时会做版本检查,版本过低或过高都会直接拒绝。

解决:不要自己装系统级 MinGW 再手动配 PATH,让支持包安装器全权管理。如果已经装了系统级 MinGW,检查系统 PATH 里是否包含了它的bin目录,把它从 PATH 的前部挪到后面,或者干脆删除,让 MATLAB 优先找到支持包内的编译器。检查方式在 MATLAB 里跑mex.getCompilerConfigurations('C++', 'Installed'),看显示的路径是不是 SupportPackages 下的那个。

5.4 现象:编译成功,运行时提示缺少 libgcc_s_seh-1.dll 或 libstdc++-6.dll

原因:MinGW-w64 编译出的 MEX 文件,启动时需要加载两个运行时 DLL——libgcc_s_seh-1.dll和libstdc++-6.dll。这两个文件在支持包的mingw64\bin目录下,但该目录不在系统 PATH 里,Windows 加载 DLL 时找不到。

解决:把支持包的bin目录加到系统 PATH。路径大概是C:\ProgramData\MATLAB\SupportPackages\R20xx\3P.instrset\mingw_w64.instrset\mingw64\bin,R20xx 换成你的 MATLAB 版本。改完 PATH 后要重启 MATLAB 才生效。如果不想动系统 PATH,也可以在启动脚本里设置环境变量:在userpath下的startup.m里写setenv('PATH', ['C:\...\mingw64\bin;' getenv('PATH')]),效果一样,只是只对 MATLAB 进程生效,不污染系统全局变量。

5.5 现象:C++ 代码编译遇到 undefined reference 到 std::string 或 std::vector 相关符号

原因:代码里用了 C++ 标准库,但链接阶段没拉入 libstdc++。MinGW-w64 的 g++ 前端正常情况下会自动链接标准库,但如果你用mex的-c选项手动编译成.o、再手动链接,就很容易漏掉-lstdc++这一步。

解决:大部分情况下,不用-c,直接让mex一条命令完成“编译 + 链接”。如果确实需要手动分步,链接命令里显式加-lstdc++。另外检查你的 C++ 源文件后缀:.c后缀会让编译器按 C 语言处理,链接时自然找不到 C++ 符号。把文件重命名为.cpp,一切都会正常。

6. 进阶用法:把编译流程固定成脚本,让验证不再靠手感

熟练之后,每次手动敲mex -setup和mex命令其实是浪费。我把自己的标准流程固定成了一个编译脚本,放在项目根目录,每次拿到新机器只需要跑一遍:

% compile_all.m if isempty(mex.getCompilerConfigurations('C++', 'Installed')) error('MinGW-w64 编译器未安装,请先安装 MATLAB Support for MinGW-w64'); end mex -O CXXFLAGS="$CXXFLAGS -std=c++17" sum_mex.cpp mex -O calc_mex.c % 自动验证 assert(abs(sum_mex(1:10) - 55) < 1e-12, 'sum_mex 计算结果异常'); assert(abs(calc_mex(2) - 9) < 1e-12, 'calc_mex 计算结果异常'); disp('全部编译和验证通过');

这个脚本的核心逻辑是先检查编译器状态,再编译,最后用断言做数值验证,不让任何一步靠手感。第一个assert验证累加函数的结果,第二个验证二次函数代入x=2时4+6-1=9的结果。任何一步失败,脚本立刻抛出错误,而不是等你在 MATLAB 里手动试函数再慢慢找问题。

另一个实用技巧是增量编译:你只改了一个源文件时,用mex -c file.cpp生成.o文件,然后链接时直接复用这个.o,可以节省大量重复编译时间。配合支持包自带的g++手动编译,能做的事比想象中大。

最后分享一个习惯:我现在拿到任何新环境,第一件事永远是先跑mex.getCompilerConfigurations('C++', 'Installed'),确认编译器状态正常,再去碰项目代码。这个习惯帮我避免了一半以上的环境类报错,希望你也能用上。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询