本文重点讨论 Visual Studio 与 Matlab 的混合编程的问题。
对于数学计算来说,用 Matlab 极其方便,于是,对于这么多用 Matlab 写成的库资源,我们如果不能在 Visual Studio 里使用,就太浪费了。
对于 Visual C++ 5.0 或是 6.0 来说,Matlab 提供了一个插件,可以在 Visual C++ 里直接进行 Matlab 的混合编程。可是对于更高版本的 Visual C++,Matlab 却没有这个插件。
这个时候,我们依然可以在 Visual Studio 里调用 Matlab 写好的程序,一般来讲,有下面三种方法:
1. 通过 mcc 将 Matlab 的 m 文件转化为 cpp、c 文件或 dll 供 VC++ 调用;
2. 通过 Matlab 的 combuilder 将 m 文件做成 COM 组件,供 VC++ 调用;
3. 通过 matcom 工具,不过 Mathworks 公司已经不在出新版本了,而且它的功能可以用第 1 和第 2 种方法代替推荐使用前两种方式。
本文主要介绍一下两大部分的内容:1. 如何用 Visual C++ 调用 Matlab 内置的函数;2. 如何用 Visual C++ 调用用户自己编写的 Matlab 函数。
现在就用 Matlab 7 和 Visual Studio 2005 来举例,介绍一下如何在 Visual C++ 里调用 Matlab 的函数。
Matlab 7 的安装没啥好说的,一路安装下去,记得安装完后重启电脑。不过为了方便起见,最好不要把 Matlab 安装到带有空格的路径里。
先把 Matlab 为 C++ 准备的头文件添加到 Visual Studio 2005 里:
在 Visual C++ 2005 里通过菜单 Tools ==> Options ==> Projects and Solutions ==> VC++ Directories ,把 Matlab 安装目录下的 extern/include 目录添加到 Include files 里(在我这里是 E:\MATLAB7\extern\include)
![]() |
| 添加 Matlab 的头文件 |
在同一个窗口里,选择 Library Files,然后把 Matlab 为 C++ 准备的库文件目录添加进去,直接把 Matlab 目录下的 extern/lib/win32/microsoft/msvc70 路径添加进去(根据相应的 VC++ 版本选择版本号,我这里是 E:\MATLAB7\extern\lib\win32\microsoft\msvc70)。
![]() |
| 添加 Matlab 库文件 |
现在我们可以创建一个工程来测试一下在 VC++ 里能不能调用 Matlab 提供的 dll 文件。
可以创建一个名为 MatlabVSTest 的 console 工程,把 Precompiled 选项激活,然后通过菜单 Project ==> Properties ,在对话框里选择 Linker ==> Input ,把安装目录下的如下几个 lib 库文件添加进去:
E:\MATLAB7\extern\lib\win32\microsoft\msvc70\libmex.lib E:\MATLAB7\extern\lib\win32\microsoft\msvc70\libmx.lib E:\MATLAB7\extern\lib\win32\microsoft\msvc70\libeng.lib
然后把下面的代码放到你的程序文件里:
#include "stdafx.h" #include <stdio.h> #include <conio.h> #include <memory.h> #include <engine.h> //Located in $Matlab$\extern\include #pragma comment( lib, "Libmx.lib" ) #pragma comment( lib, "libmex.lib" ) #pragma comment( lib, "libeng.lib" ) #define SIZE 50 int _tmain(int argc, _TCHAR* argv[]) { double x[SIZE], y1[SIZE], y2[SIZE]; for (int i=0; i<SIZE; i++) { x[i]=((double)i)*0.1; y1[i]=x[i]*x[i]; y2[i]=y1[i]*x[i]; } Engine *m_pEngine; m_pEngine = engOpen(NULL); if (m_pEngine == NULL) { //Error! Fail to connect to MATLAB engine. // The plot function will be disabled! printf("Fail to open MATLAB Engine!\n"); exit(0); } //Translate data from C++ to Matlab mxArray *m_X, *m_Y1, *m_Y2; m_X=mxCreateDoubleMatrix(1, SIZE, mxREAL); memcpy((void *)mxGetPr(m_X), (void *)x, sizeof(double)*SIZE); engPutVariable(m_pEngine, "x", m_X); m_Y1=mxCreateDoubleMatrix(1, SIZE, mxREAL); memcpy((void *)mxGetPr(m_Y1), (void *)y1, sizeof(double)*SIZE); engPutVariable(m_pEngine, "y1", m_Y1); m_Y2=mxCreateDoubleMatrix(1, SIZE, mxREAL); memcpy((void *)mxGetPr(m_Y2), (void *)y2, sizeof(double)*SIZE); engPutVariable(m_pEngine, "y2", m_Y2); //Plot by sending command to engine engEvalString(m_pEngine, "plot(x, y1, '-', x, y2, ':');"); engEvalString(m_pEngine, "title('y_1/y_2 vs. x')"); engEvalString(m_pEngine, "xlabel('x');"); engEvalString(m_pEngine, "ylabel('y (Unit:10)');"); printf("Press any key to close the plot...\n"); getch(); //Close plot window engEvalString(m_pEngine, "close;"); engClose(m_pEngine); printf("Press any key to exit...\n"); getch(); return 0; }
编译和运行上面的代码,看看你是否能得到下面的结果:
![]() |
| 运行结果 |
运行上面的代码,如果出现了如下的错误(如下图所示):
This application has failed to start because libmx.dll was not found. Re-installing the application may fix this problem.
![]() |
| Link Error |
这个时候,很可能是你安装完 Matlab 后没有重启电脑造成的。
很多情况下,我们会在 Matlab 里写一大堆的 m 文件,用以完成我们自己的工作。如果这部分算法是用 Matlab 完成的,我们需要在 C++ 里用到,我们可以直接把这些 m 文件编译成 dll ,从而在 C++ 里直接调用它们。
从 Matlab 的命令行里直接把 m 文件编译成 DLL ,可以使用下面的命令:
mcc -W lib:liba -T link:lib a0 a1
上面的命令从文件 a0.m 和 a1.m 生成一个名为 liba 的动态链接库。
上面这个命令会生成 mylib.dll, mylib.lib and mylib.h 等几个文件,如果想在 MSVC 里生成 debug 版本的程序,则需要加上 -g 这个参数。更多有关命令 mcc 的帮助可以在 Matlab 里查看 help mcc 来获得。
我们可以试着用上面的命令来编译下面的程序,程序如下:
function y=MeanFunction(x) [m,n]=size(x); k=0; for i=1:n k=k+x(i); end y=k/n;
我们用下面的命令来进行编译:
mcc -W lib:MeanFunctionLib -T link:lib MeanFunction.m
该命令会在当前的 work 目录生成 meanfunctionlib.h , meanfunctionlib.c, MeanFunctionLib.dll 和 MeanFunctionLib.lib 等相关文件。
我们新建一个 VC++ Console 工程,然后把下面的代码拷进去:
#include "stdafx.h" #include "matlab.h" #include "MeanFunctionLib.h" #pragma comment(lib, "libmx.lib") #pragma comment(lib, "libmatlb.lib") #pragma comment(lib, "libmat.lib") #pragma comment(lib, "libmmfile.lib") #pragma comment(lib, "MeanFunctionLib.lib") int main(int argc, char* argv[]) { mxArray* result; mxArray* x; double myArray[5]={10.2, 3, 6.3, 5.4, 5.9}; x=mxCreateDoubleMatrix(1, 5, mxREAL); memcpy(mxGetPr(x), myArray, 5 * sizeof(double)); MeanFunctionLibInitialize(); result=mlfMeanfunction(x); MeanFunctionLibTerminate(); mlfPrintMatrix(result); mxDestroyArray(x); mxDestroyArray(result); return 0; }
前面通过两个例子,简单地说明了如何在 VC++ 里调用 Matlab 内嵌的函数或是自己的函数,现在来详细说一下有关 Matlab 与 C 关联的语法,即如何从 C 语言的角度来解读 Matlab 的函数。
参考文章出处:
1. http://wibirama.com/dip/wp-content/uploads/2008/11/matlab-and-ms-studio.pdf
2. http://www.codeproject.com/KB/cpp/matlab_cpp.aspx
3. http://www.codeproject.com/KB/DLL/MatlabSharedLib.aspx