C调用Matlab编译DLL传递字符串参数时路径报错问题求解
问题背景
需要实现从C代码向Matlab函数传递字符串类型的文件名入参,Matlab端逻辑为根据传入的名称查找对应数据文件,加载文件内数据到矩阵。Matlab端函数代码如下:
function bus = new(casefile) { A=loadcase(casefile); % 对数据做额外处理后返回复数双精度矩阵 }
通过Matlab Compiler将该Matlab函数编译为DLL文件,编写C侧测试代码传递文件名参数调用,C代码如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "matrix.h" #include "new.h" int run_main(int argc, const char** argv) { mxArray* casename; mxArray* sbus=NULL; sbus = mxCreateDoubleMatrix(9, 1, mxCOMPLEX); casename = mxCreateString("case9.m"); if (!newInitialize()) { fprintf(stderr, "Could not initialize the library.\n"); return -2; } else { /* 调用库函数 */ mlfnew(1, &sbus, casename); newTerminate(); mxDestroyArray(casename); } mclTerminateApplication(); return 0; } int main(int argc, const char** argv) { if (!mclInitializeApplication(NULL, 0)) { fprintf(stderr, "Could not initialize the application.\n"); return -1; } return mclRunMain((mclMainFcnType)run_main, argc, argv); }
程序运行时抛出如下报错:
loadcase: specified M file does not exist
loadcase: specified case not in MATLAB's search path
已完成的排查操作:
- 尝试在传入的文件名字符串中加入完整目录绝对路径,报错未解决
- 确认数据文件与Matlab函数位于同一目录,且该目录已添加至本地Matlab搜索路径
解决方案
- 核心问题:动态依赖文件未被打包进编译产物
Matlab Compiler编译DLL时,只会静态扫描代码中显式调用的函数和依赖,通过字符串参数动态加载的文件(比如loadcase读取的case9.m)不会被自动识别并打包进CTF归档包。编译后的程序运行在独立的MCR环境中,和你本地Matlab的搜索路径配置完全隔离,哪怕你本地已经把目录加进Matlab路径,MCR运行时也读不到这些文件。
编译时必须手动将所有需要动态加载的case数据文件添加到编译配置的「Additional Files」列表中,确保文件被打入CTF包。 - 修正Matlab端运行时路径逻辑
CTF包在程序运行时会被解压到临时目录,和你本地源码存放路径无关,直接传本地绝对路径或者裸文件名都无法定位文件,需要在Matlab函数内适配编译后的运行环境:
注意:原Matlab函数用大括号包裹函数体属于语法错误,Matlab函数不需要大括号包裹代码块,直接在function声明后编写逻辑即可。function bus = new(casefile) % 去除文件名后缀,loadcase不需要.m后缀 casefile = erase(casefile, ".m"); % 编译运行环境下自动配置路径 if isdeployed addpath(ctfroot); end A = loadcase(casefile); % 后续数据处理、返回复数矩阵逻辑 end - 修正C侧调用逻辑
- 创建字符串入参时不要带
.m后缀,直接传入mxCreateString("case9")即可。 - 不需要提前调用
mxCreateDoubleMatrix创建sbus,输出参数的mxArray由mlf接口自动分配内存,提前创建的矩阵会造成内存泄漏甚至参数传递错误,保持sbus = NULL初始化即可。 - 若调试时需要定位路径问题,可在初始化MCR后开启日志打印,直接查看运行时实际搜索的文件路径列表,避免传本地开发机的无效绝对路径。
- 创建字符串入参时不要带
- 可选:C侧显式添加MCR搜索路径
如果不把数据文件打进CTF包,而是放在C程序同级目录,可在调用newInitialize()后,通过MCR提供的接口将程序当前目录显式加入MCR搜索路径,MCR默认不会读取系统环境变量或程序当前工作目录。
内容的提问来源于stack exchange,提问作者S2022
相关产品推荐
相关产品推荐

