VS或VC调用matlab程序dll路径配置及错误分析
来源:互联网 发布:南风知我意gl网盘资源 编辑:程序博客网 时间:2024/05/22 08:25
vc6.0版本的
1:在matlab中选择compiler。
在命令行窗口输入:mex -setup
按照提示选择vc6.0.由于使用的是matlab7,不识别vs2010和2008,无奈有装的vc6.0。但听说最新版的matlab可以识别。
2:选择builder.
输入:mbuild -setup
同样选择vc6.0
3:生成dll。
输入:mcc -W cpplib:mydll -T link:lib test.m
众所周知Matlab的强大运算能力让各种工程软件望而却步,而VC程序的友好界面又让人爱不释手,如果能够让两者的优势结合起来的话,势必能让程序员欢欣鼓舞。还好MathWorks已经为我们想到了,基本上现在市面上主流的Matlab版本都可以支持VC和Matlab的混合编程。但是目前网上资料基本上都是基于Matlab 6.0和VC 6.0的,和新版本的实现方法有所不同,因此笔者通过不断的尝试和研究,终于调试通了基于VS2008和Matlab R2010b的混合编程。
为了更加直观的说明如何实现混合编程,笔者写了一个简单的程序作为测试。先在Matlab里面写一个M文件,代码如下:
function b = MyFunc(a)
b = a.*a;
将M文件保存为MyFunc.m,保存在F:/test文件夹中。然后在Matlab主窗口中将当前文件夹改为F:/test:
cd F:/test;
为了能够让VC调用Matlab程序,我们可以采用将Matlab程序包装成动态链接文件DLL的形式,然后让VC调用动态链接文件,因此在Matlab中,我们需要设置一下Matlab的编译库,在Matlab主窗口中键入如下代码:
mbuild –setup
然后出现
Please choose your compiler for buildingstandalone MATLAB applications:
Would you like mbuild to locate installedcompilers [y]/n?
键入y后回车,出现
Select a compiler:
[1] Lcc-win32 C 2.4.1 inD:\PROGRA~1\MATLAB\R2010b\sys\lcc
[2] Microsoft Visual C++ 2008 SP1 inD:\Program Files\Microsoft Visual Studio 9.0
[0] None
Compiler:
由于我们是需要用VC来调用Matlab函数,因此我们选择2,回车,出现
Please verify your choices:
Compiler: Microsoft Visual C++ 2008 SP1
Location: D:\Program Files\Microsoft VisualStudio 9.0
Are these correct [y]/n?
确定,键入y后回车,出现
****************************************************************************
Warning: Applications/components generated using Microsoft VisualStudio
2008 require that the Microsoft Visual Studio 2008 run-time
libraries be available on the computer used for deployment.
To redistribute your applications/components, be sure that the
deployment machine has these run-time libraries.
****************************************************************************
Trying to update options file: C:\Users\张智宇\AppData\Roaming\MathWorks\MATLAB\R2010b\compopts.bat
From template: D:\PROGRA~1\MATLAB\R2010b\bin\win32\mbuildopts\msvc90compp.bat
Done . . .
如果出现以上说明,则证明Matlab编译器设置成功了。接下来是生成M文件的DLL文件。
在Matlab主窗口中键入如下代码
mmc –W cpplib:MyDLL –T link:lib MyFunc.m –C
其中cpplib:后面的是需要生成文件的文件名,是自己取的,link:lib后面的MyFunc.m是转换为DLL的M文件的文件名。 -W/-T/-C是参数,具体含义可以通过mcc –help命令查看,注意参数的大小写。
Matlab编译后会在Test文件夹下生成9个文件,分别是:
mccEcxludedFiles.log
MyDLL.cpp
MyDLL.ctf
MyDLL.dll
MyDLL.exp
MyDLL.exports
MyDLL.h
MyDLL.lib
readme.txt
其中MyDLL.dll,MyDLL.lib,MyDLL.ctf,MyDLL.h是我们需要的文件,至此,Matlab方面就已经设置妥当了。
打开VC2008,新建一个工程,然后将上述四个文件复制到工程目录下。选择“工具-选项-项目和解决方案-VC++目录”,在“显示以下内容目录”里选择“包含文件”将“D:\Program Files\MATLAB\R2010b\extern\include”添加进去,然后选择“库文件”将“D:\Program Files\MATLAB\R2010b\extern\lib\win32\microsoft”添加进去,其中D:\ProgramFiles是Matlab的安装目录,可根据实际情况进行修改。
然后选择“项目-属性-配置属性-链接器-输入”,在右边“附加依赖项”一栏填入“myDLL.lib mclmcrrt.lib”,其中MyDLL.lib就是刚刚用Matlab生成的lib文件。
在编写代码时首先得包含头文件“MyDLL.h”,然后开始编写需要的代码,我为了说明问题编写了一个测试代码如下所示:
{
MyDLLInitialize(); //初始化DLL动态连接文件
double _x[5] = {1,2,3,4,5}; //输入数组
double _y[5]; //输出数组
mxArray* x = mxCreateDoubleMatrix(1, 5,mxREAL); //创建1*5矩阵
memcpy(mxGetPr(x), (void*)_x,sizeof(_x)); //拷贝输入数据
mxArray *input[1] = {x}; //将矩阵x的指针作为输入参数传递进去
mxArray *output[1]; //定义输出参数指针
mlxMyFunc(1,output,1,input); //调用m函数
mxArray *y; //定义输出结果指针
y = output[0]; //将输出参数传递给输出结果
memcpy(_y, mxGetPr(y), sizeof(_y)); //拷贝输出数据
MyDLLTerminate(); //结束DLL库
//显示数组中的数据
CString str;
str.Format("%f %f %f %f%f",_y[0],_y[1],_y[2],_y[3],_y[4]);
MessageBox(str);
}
其中MyDLLInitialize(),mlxMyFunc(),MyDLLTerminate()等函数可以在MyDLL.h中找到函数原型,mlxMyFunc函数原型为:
mlxMyFunc(int nlhs, mxArray *plhs[], intnrhs, mxArray *prhs[])
nlhs代表输出参数个数,plhs[]里面存放的是输出参数的指针,nrhs代表输入参数个数,prhs[]中存放的是输入参数的指针。上例中由于输入输出参数只有一个,因此在plhs[0]中存放的就是M文件中b的指针,prhs[0]中存放的就是M文件中a的指针。
编译运行之后就可以在弹出的消息框中得到所要的结果。将项目文件夹下生成的可执行文件复制出来,将MyDLL.dll文件、MyDLL.ctf文件和.exe文件放在同一目录下便可脱离VC++独立运行。如果需要在其他未装Matlab的机器上运行,则还需要将“D:\Program Files\MATLAB\R2010b\toolbox\compiler\deploy\win32”中的MCRInstaller.exe复制出来,在未安装Matlab的电脑上运行此程序,才可使得刚刚生成的可执行文件顺利运行。
以上程序在Windows 7 家庭普通版 + Visual Studio 2008 专业版 SP1 + Matlab R2010b下编译运行通过。
vs2008版本
在Matlab中,编写一个M文件(myadd.m),保存
function [y,z] = MyAddAndMulti(a, b)
% define function, just to demonstrate the idea
y = a+b;
z = a*b;
end
上述函数实现单独的数或者是数组相加和相乘。
设置matlab编译器
过程如下:
1. 在matlab的command window里面敲入mex –setup,(此命令不允许-和setup有空格)matlab会列出所有电脑上所有的编译器。
2. 选择编译器
3.完成之后,敲入mbuild –setup,选择build工具
在MATLAB的command window中输入以下命令:
mcc -W cpplib:MyAddAndMulti -T link:lib MyAddAndMulti.m
在Matlab窗口,可能出现以下警告:
To get started, select MATLAB Help or Demos from the Help menu. Warning: No matching builtin function available for D:\MATLAB7\toolbox\simulink\simulink\set_param.bi
此时,可以进行如下操作:
将 \MATLAB7\toolbox\compiler\deploy\matlabrc.m 中的
81 行 set_param(0,'PaperType',defaultpaper);82 行 set_param(0,'PaperUnits',defaultunits);
用’%‘注释掉之后,全部选中重新编译了一次,然后重新启动 matlab 就没有警告信息。
上述过程中,matlab中的工作目录要选择好,否则发生下述错误:
??? Error: File "MyAddAndMulti" not found.
在VS平台上(VS2008)
新建工程(win32控制体),完成之后,界面变为
这个时候,在 项目->属性,后可以看到
这个看不到C/C++相关设置,需要在我们建的工程中,加上一个CPP文件后,
此时在C/C++下面
添加附加包含目录
接下来
添加链接库的东西,libmyadd3.lib mclmcrrt.lib mclmcr.lib
运行差不多就对了。
----------------------可能错误---------------------------------------------------------------
发生错误: LINK : fatal error LNK1104: 无法打开文件“mclmcrrt.lib”
解决办法: 在链接器->常规->附加库目录地方没有添加 D:\matlab\extern\lib\win32\microsoft\msvc60(目录视安装情况而定)
建议方案:在matlab中的M文件最好都小写,因为在生成dll和lib的时候,部分为全部小写而部分保持原样。
vc6.0与vs08使用VC6.0与VS2008,在配置上面都是类似的,唯一的区别在与用蓝色标出的部分
一. MATLAB Compiler
配置MATLAB编译器,主要是在MATLAB的命令窗口先后输入两条命令:"mex -setup"和"mbuild -setup",然后选择对应的编译器即可。由于使用VC++6.0,所以在我的机器上,选择编译器的地方都是输入3;需要输入[y]/n的地方就输入y。(注意第1行、第10行、第19行、第26行、第53行、第62行、第71行和第78行。)
1. 做最简单的MATLAB程序,代码如下:二. 编写MATLAB代码
1
function
C = Add(A,B)
2
C = A+
B;
然后在R盘根目录下新建DLL文件夹,把上面的代码存到该文件夹下,文件名为Add.m
2. 在MATLAB命令窗口下输入:
1
>> cd R:\DLL
2
>> mcc -W cpplib:libAdd -T link:lib Add.m
这样,在"R:\DLL"文件夹下,会生成一堆文件,其中有三个是需要的:"libAdd.dll"、"libAdd.h"和"libAdd.lib"。
三. 配置工程环境
1. 打开VC后,新建一个Win32 Console Application,工程名MATLABDLL,存放到R盘根目录。
2. 进入工程后,在工程中新建一个C++ Source File,命名为Test。
3. 把上面生成的"R:\DLL"中的"libAdd.dll"、"libAdd.h"和"libAdd.lib"三个文件,拷贝到"R:\MATLABDLL"目录下。
4. 回到VC6,在工程中右键点击"Header Files",选择"Add Files to Folder",把"R:\MATLABDLL"下的"libAdd.h"添加进工程。
双击打开"libAdd.h",把代码拖到最后,可以看到这么一行:
1
extern
LIB_libAdd_CPP_API
void
MW_CALL_CONV Add(
int
nargout, mwArray& C,
const
mwArray& A,
const
mwArray& B);
可见Add函数在C++中调用和在MATLAB中调用不一样,需要提供4个参数,第一个参数是返回值的个数(本例中只有一个返回值,故为1),第二个到第四个参数恰好是输出和输入(都是mwArray引用,后面再来看怎么用它)。
5. 配置工程MATLABDLL的Include Files环境,选择"Tools"菜单中的"Options"选项:
进入到"Directories"选项卡,选择"Include files",把MATLAB安装路径下的include文件夹加入,我本机的路径是" C:\Program Files\MATLAB\R2011b\extern\include"。
6. 配置工程MATLABDLL的Library files环境:依旧在"Directories"选项卡下,选择"Library files",把MATLAB安装路径下的lib文件夹加入,我本机的路径是"C:\Program Files\MATLAB\R2011b\extern\lib\win32\microsoft"。这里需要注意的是,该路径下有" mclmcrrt.lib"文件,是我们需要的。
7. 选择"Project"菜单中"Settings"选项:
进入"Link"选项卡,Category选择"Input",把"mclmcrrt.lib"和"libAdd.lib"加在最后。(这里需要注意的是,如果你的代码要分别生成Debug和Release版程序,则在左边"Settings For"中对"Win32 Debug"和"Win32 Release"都进行这样的设置。参考资料[3]中提示要加入以下几个LIB库:mclmcrrt.lib, mclmcr.lib, mclbase.lib, mclcommain.lib,这里暂时加第一个就够了。)
至此,环境配置完毕。
四. 编写代码调用DLL
在工程中打开"Test.cpp",编写如下代码。该代码中包含两段对Add函数的测试,第一段是测试两个整数相加,第二段是测试两个矩阵相加。
#include "iostream.h"#include "libAdd.h"
int main()
{
//初始化lib(必须)
if (!libAddInitialize())
return -1;
//测试两个整数相加
int a = 10, b = 20;
int c;
mwArray mwA(1,1,mxINT32_CLASS);
mwArray mwB(1,1,mxINT32_CLASS);
mwArray mwC(1,1,mxINT32_CLASS);
mwA.SetData(&a, 1);
mwB.SetData(&b, 1);
Add(1, mwC, mwA, mwB);
c = mwC.Get(1,1);
cout<<"c = "<<c<<endl<<endl;
//测试两个double型矩阵相加
double da[2][2] = {1,2,3,4}, db[2][2] = {5,6,7,8};
double dc[2][2];
mwArray mwDA(2,2,mxDOUBLE_CLASS);
mwArray mwDB(2,2,mxDOUBLE_CLASS);
mwArray mwDC(2,2,mxDOUBLE_CLASS);
mwDA.SetData(*da, 4);
mwDB.SetData(*db, 4);
Add(1, mwDC, mwDA, mwDB);
cout<<"dc = "<<endl;
for(int i = 0; i < 2; i++)
{
for(int j = 0; j < 2; j++)
{
//Get第一个参数表示用2个下标访问元素(即i和j),j+1是列号,i+1是行号(MATLAB要求以列为先序)
dc[i][j] = mwDC.Get(2,j+1,i+1);
cout<<" "<<dc[i][j];
}
cout<<endl;
}
//终止调用
libAddTerminate();
//mclTerminateApplication();
return 0;
}
几点说明:
(1) 第7行初始化lib的代码貌似是必须的,否则我这里运行出错;而第44行和第45行的终止调用,貌似注释掉也没有什么影响。
(2) mwArray对象有多种初始化方式,这里第13-15行表示初始化成1x1的int32类型对象,第25-27行表示初始化成2x2的double类型对象。
(3) SetData函数第一个参数是一个mwArray型的一级指针,第二个参数表示元素个数。由于a,b是一个int型的变量,故第16-17行对a,b做取地址运算;而da和db由于是二维数组名,即二级指针常量,故第28-29行对da,db做了一级指针引用。
(4) Get函数也有多种调用形式。第19行调用中,Get函数第一个参数1,表示只用1个下标来访问(类似于MATLAB中可以把一个矩阵看作是一个向量,以列为先序),第二个参数1表示访问第1个元素;而第37行调用中,Get函数第一个参数2,表示用2个下标来访问(i是行索引,j是列索引,又由于是以列为先序,所以j在前,i在后),同时由于MATLAB中下标是从1开始,而C++中下标是从0开始,故做了j+1和i+1操作。
运行代码,程序的执行结果是:
- VS或VC调用matlab程序dll路径配置及错误分析
- VS或VC调用matlab程序
- VS或VC调用matlab程序
- VS或VC调用matlab程序
- vc调用matlab的dll
- vs c++ 调用matlab编译的dll
- matlab调用VS生成的DLL
- matlab调用VS生成的DLL
- VC++ 创建及调用Dll
- vc调用matlab生成的dll实例
- VC调用MATLAB 产生的dll文件
- VC调用Matlab生成的DLL
- VC调用Matlab生成的dll
- 64位Win7系统下配置VC/VS调用32位matlab
- DLL文件 VC++&Matlab混合编程( 调用DLL)
- VC与Matlab混合编程(在VC中调用DLL)
- VC与Matlab混合编程(在VC中调用DLL) .
- VC与Matlab混合编程(在VC中调用DLL)
- shader 一
- 网页布局时的,a标签
- Android中使用腾讯的SDK完成分享图文到qq空间
- Java保留小数位的四种方法
- 使用CXF+spring+restful创建一个web的接口项目
- VS或VC调用matlab程序dll路径配置及错误分析
- 关于吸血鬼数字的获取
- Locate and Attack Domain SQL Servers without Scanning
- windows下用vim实现qt代码的自动补全功能
- pkg-config的安装配置及其作用
- 第三篇——第二部分——第三文 配置SQL Server镜像——域环境
- 物种分布建模的例子
- [Android内存分析] 使用MAT工具做内存泄露分析一
- 黑马程序员——认识JAVA