Matlab高阶应用——matlab工程程序转成C,并在VC2010环境下编译运行(codesgen)
参考:http://www.chinadmd.com/file/xtvatuzuiwscixvszrupaoct_4.html
Matlab程序转成C,并在VC2010环境下编译运行
前提:VC2010是32位的,所以对应的Matlab程序也应该要安装32位的;本人电脑64位,之前安装了64位的Matlab,无法使用VC2010编译器,后来再装了个32位的。
1.Matlab程序写法及转成C代码参见Matlab帮助文档:命令codegen
运行完codegen myFunctionname 后,Matlab会将用户定义的函数转换成一系列C语言代码,代码在Matlab工作目录下的codegen文件夹下。
2. 介绍转换代码功能;
Matlab在使用codegen生成C语言代码的同时,编译生成相应的.mex文件;以test.m函数转换成C语言代码为例。执行完“codegen test”后,会生成test.c; test_api.c; test_data.c;
test_initialize.c; test_mex.c; test_terminate.c,以及与之对应的头文件;同时生成test_mex.mex文件。熟悉matlab与C混合编程的朋友知道,执行codegen命令同时生成的.mex文件实质是编译这些C文件生成的;根据.mex文件名,可知程序的函数入口在test_mex.c文件中。
在文件test_mex.c文件中,找到程序入口函数void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])。其中nlhs为输出参数个数;plhs为输出参数对应的指针;nrhs和prhs为对应的输入参数信息。寻着函数调用关系深入,可以发现:
先调用test_initialize()函数对参数变量初始话;进而调用test_api()函数,在test_api函数中调用test()函数,即功能函数,执行完成后,调用test_terminate()函数结束。
3. Matlab转C部分小结及使用:
Matlab本身功能就很强大了,效率也很高,尤其是在矩阵运算方面;将Matlab函数转成C的主要目的是为了提高运算效率;用户可以将“循环”、“积分”等耗时的运算写成一个函数,利用codegen将该部分转成C函数文件,同时生成.mex,通过这样处理之后,通过调研.mex文件,可以几何级的提高运算效率。基于转换成的C文件,根据第2部分的介绍,用户可以找到C文件中相应需要调整修改的参数,直接修改保存,运行同一目录下的test_mex.bat批处理文件,将根据修改后的C文件生成新的.mex文件。
根据上面的介绍,对应一般的使用已经足够,下面介绍VC环境下编译转换成的C文件。
1. 配置VC编译器:
VC2010中新建win32控制台程序;将Matlab工程转换成的所有.c和.h的文件拷贝到VC工程目录中;填加到工程中;配置工程属性。选中工程名“右键”-“属性”;
在系统配置中C/C++下,添加include和references目录: (如图1所示)
图1. 在系统配置中C/C++下,添加include和references目录
Include: **\Program Files(x86)\MATLAB\R2011b\extern\include
**\Program Files(x86)\MATLAB\R2011b\extern\include\win32
References: **\Program Files(x86)\MATLAB\R2011b\extern\lib\win32\microsoft
在Linker\Input中,添加Additional Dependencies,即lib文件: (如图2所示)
图2. 添加lib文件
(注)需要具体哪些lib文件,可先编译,缺什么找什么。Lib文件查找目录在References:**\Program Files(x86)\MATLAB\R2011b\extern\lib\win32\microsoft目录下;如编译报错说error LNK2019: unresolved external symbol _mexPrintf referenced in function _MainFunc;参见References目录下的lib文件,根据提示“_mexPrintf”,说明可能是libmex.lib文件。在Additional
Dependencies中添加之后,不报错说明就是缺少该lib文件,报错说明缺少的可能是别的。经过这样多次,最终顺利找到所有lib文件。
注意,在编译寻找缺失的lib文件前,需要将mexFunction注释掉,换成Main(),并添加mexFunction函数输入的初始定义,如图3所示:
图3. 修改相应代码
Lib文件配置成功后,编译将不会出错,但是会报错找不到各种动态链接库(.DLL)。
2.寻找缺失的.DLL文件:
对于简单的问题,缺失的.DLL基本都在*:\Program Files (x86)\MATLAB\R2011b\bin\win32目录下;
(请容许这里我多说两句,因为走向胜利的道路实在太坎坷了,不过这个过程确实很有意义) 最开始我的处理方式是编译运行程序,报错(缺少***.DLL),然后在目录下寻找,复制到我的工程文件目录下;当复制完所有的DLL之后,程序报错0xc000007b error "The application was unable to start correctly 0xc000007b";网上各种建议,最后采纳的提议为:采用VC自带的
dumpbin.exe(C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin),查是否因为32位和64位的.DLL混合调用造成的;运行dumpbin.exe的时候报错缺少“mspdb80.dll”后来再网上找到解决,修改环境变量path,详细见(http://blog.csdn.net/yaneng/article/details/5415822)解决
dumpbin.exe问题后,“开始”-“运行”-cmd 到doc界面,cd ..到程序目录,dumpbin /Header test.exe,查看test.exe的信息。后来发现没用。接着下载dependency walker小程序
(http://www.dependencywalker.com/),解压运行,打开要检查的.exe程序;将查出你缺少了那些DLL,我发现我的程序缺少的DLL太多了,
后来无赖,将matlab\bin目录下的所有DLL复制到了工作文件中,问题成功解决。
3. 报新的DLL缺失
完成上一步工作后,对于大部分程序都没有问题了,但我的工程比较庞大,里面涉及一些看上去无关紧要的程序段,出现地址指针的报错,我直接将其注释掉了,结果证明确实是无关紧要的,(如图4所示)
图4. 注释掉部分报错信息
但是还是出现新的错误,程序break到图5中的位置,报错信息缺少refblas.DLL。Matlab的bin目录下没有该DLL,电脑上其他位置也没有,从别的朋友那里Matlab2008的bin目录下找到该DLL,拷贝过来报错,后来在网上找到该DLL(),添加进工程目录,问题成功解决。
图5. 中断位置degmm32,缺失refblas.DLL
4. 至此,成功实现将Matlab中codegen生成的C语言文件在VC2010环境下编译运行成功。(花了两天解决该问题,三小时整理这些东西,希望对您有用,欢迎讨论)