使用 MinGW -w64 编译 C/C++ MEX 文件的限制和疑难解答
不要链接到使用非 MinGW 编译器编译的库文件
如果您使用 MinGW® 编译器编译的 MEX 文件链接到使用非 MinGW 编译器(例如 Microsoft® Visual Studio®)编译的库,该文件将不会在 MATLAB® 中运行。由不同编译器生成的库 (.lib) 文件彼此不兼容。
您可以使用来自 MinGW 的 dlltool 实用工具来生成新的库文件。
MinGW 安装文件夹名称不能包含空格
不要将 MinGW 安装在路径名中包含空格的位置。例如,不要使用:
C:\Program Files\mingw-64
应改用:
C:\mingw-64
MEX 命令不选择 MinGW
如果在您的系统中仅安装了 MinGW 编译器,则 mex 命令会自动为 C 和 C++ MEX 文件选择 MinGW。如果您有多个 C 或 C++ 编译器,请使用 mex -setup 来为 C 和 C++(如果需要)MEX 文件选择 MinGW。
mex -setup mex -setup cpp
如果您仅键入了 mex -setup 来选择 MinGW,则在编译 C++ 文件时,mex 可能会选择其他编译器。
手动为 MATLAB 配置 MinGW
从 MATLAB 附加功能菜单安装 MinGW 时,MATLAB 会自动检测 MinGW 编译器。
如果需要,您可以手动配置 MinGW;如果您有 Windows® 管理特权,可以使用 configuremingw 脚本。要下载此脚本,请参阅 MATLAB Answers 文章 "I already have MinGW on my computer.How do I configure it to work with MATLAB"。
MinGW 的行为与 Linux 中的 gcc/g++ 相似
当使用 mex 命令修改编译器标识符时,请使用 Linux® 编译器标识符 CFLAGS 或 CXXFLAGS,而不是 Windows 标识符 COMPFLAGS。
C++ MEX 文件内有关使用 MEX 异常的潜在内存泄漏
使用 MinGW-w64 编译器编译的 C++ MEX 文件中的错误处理与 MATLAB 的错误处理不一致。如果 C++ MEX 文件包含某个类,则使用 mexErrMsgIdAndTxt 函数抛出 MEX 异常可能导致为该类创建的对象发生内存泄漏。
MathWorks 建议您使用 C++ MEX API,而不是 C Matrix API。有关详细信息,请参阅编写可从 MATLAB(MEX 文件)调用的 C++ 函数。
例如,以下 C++ MEX 函数包含类 MyClass。
#include "mex.h"
class MyClass {
public:
MyClass() {
mexPrintf("Constructor called");
}
~MyClass() {
mexPrintf("Destructor called");
}
};
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
MyClass X;
if (nrhs != 0) {
mexErrMsgIdAndTxt("MATLAB:cppfeature:invalidNumInputs",
"No input arguments allowed.");
}
}
该 MEX 函数从 MyClass 创建了对象 X,然后检查输入参量的数量。如果该 MEX 函数调用 mexErrMsgIdAndTxt,则 MATLAB 错误处理不会释放对象 X 的内存,从而产生内存泄漏。
C++ MEX 文件中未处理的显式异常意外终止 MATLAB
如果 C++ MEX 文件中的某个函数抛出一个显式异常,而该异常未在 MEX 文件内使用 catch 语句捕获,则该异常会导致 MATLAB 终止,而不是向 MATLAB 命令行传播错误。
#include "mex.h"
class error {}; // Throw an exception of this class
class MyClass
{
public:
MyClass(){
mexPrintf("Constructor called.");
}
~MyClass(){
mexPrintf("Destructor called.");
}
};
void doErrorChecking(const MyClass& obj)
{
// Do error checking
throw error();
}
void createMyClass()
{
MyClass myobj;
doErrorChecking(myobj);
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
createMyClass();
}MEX 函数调用 createMyClass,后者创建 MyClass 类的一个对象,并调用函数 doErrorChecking。函数 doErrorChecking 会抛出 error 类型的异常。但此异常未在 MEX 文件内捕获,从而导致 MATLAB 崩溃。
对于从 std::exception 类继承的类,也会发生此行为。
解决方法
在 MEX 函数中捕获异常:
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
try{
createMyClass();
}
catch(error e){
// Error handling
}
}