DLL文件 VC++&Matlab混合编程( 调用DLL)

VC++ 专栏收录该内容
3 篇文章 0 订阅

lib和dll文件的区别和联系

lib是和dll对应的。lib是静态链接库的库文件,dll是动态链接库的库文件。 
所谓静态就是link的时候把里面需要的东西抽取出来安排到你的exe文件中,以后运行你的exe的时候不再需要lib。
所谓动态就是exe运行的时候依赖于dll里面提供的功能,没有这个dll,你的exe无法运行。 

lib,dll,exe都算是最终的目标文件,是最终产物。而c/c++属于源代码。源代码和最终目标文件中过渡的就是中间代码obj,实际上之所以需要中间代码,是你不可能一次得到目标文件。比如说一个exe需要很多的cpp文件生成。而编译器一次只能编译一个cpp文件。这样编译器编译好一个cpp以后会将其编译成obj,当所有必须要的cpp都编译成obj以后,再统一link成所需要的exe,应该说缺少任意一个obj都会导致exe的链接失败。

1.obj里存的是编译后的代码跟数据,并且有名称,所以在连接时有时会出现未解决的外部符号的问题。当连成exe后便不存在名称的概念了,只有地址。lib就是一堆obj的组合。
2.理论上可以连接obj文件来引用其他工程(可以认为一个obj文件等价于编译生成它的cpp文件,可以引用obj来替换cpp,也可以添加cpp来替换obj ),但实际中通常用lib来实现工程间相互引用。
3.编译器会默认链接一些常用的库,其它的需要你自己指定。

lib和DLL的区别 

(1)lib是编译时需要的,dll是运行时需要的。如果要完成源代码的编译,有lib就够了。如果也使动态连接的程序运行起来,有dll就够了 。在开发和调试阶段,当然最好都有。 
(2) 一般的动态库程序有lib文件和dll文件。lib文件是必须在编译期就连接到应用程序中的,而dll文件是运行期才会被调用的。如果有dll文件,那么对应的lib文件一般是一些索引信息,具体的实现在dll文件中。如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。 静态编译的lib文件有好处:给用户安装时就不需要再挂动态库了。但也有缺点,就是导致应用程序比较大,而且失去了动态库的灵活性,在版本升级时,同时要发布新的应用程序才行。 
(3)在动态库的情况下,有两个文件,一个是引入库(.LIB)文件(实际上也算是一个静态库,只是在链接时只能把函数在DLL的入口链接到exe中,而不像真正静态链接库那样将函数体真正链接到exe中 ,通过lib进行的动态链接实际上也使用了静态链接来实现 ),一个是DLL文件,引入库文件包含被DLL导出的函数的名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到所需要使用的DLL文件,库中的函数和数据并不复制到可执行文件中,因此在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址,这样当一个或多个应用程序运行是再把程序代码和被调用的函数代码链接起来,从而节省了内存资源。从上面的说明可以看出,DLL和.LIB文件必须随应用程序一起发行,否则应用程序将会产生错误。

DLL内的函数分为两种: 
(1)DLL导出函数,可供应用程序调用;
(2)DLL内部函数,只能在DLL程序使用,应用程序无法调用它们

创建静态链接库和创建动态链接库

VC6中创建[Win32 Dynamic-Link Library]工程便可以创建出一个空的DLL工程.

VC6中创建[Win32 Static Library]工程便可以创建出一个空的LIB工程(静态链接库工程,仅生成一个lib文件).

添加lib文件的常用办法有二个: 
1、把*.lib放在VC的Lib目录中 
2、修改project setting的Link->Input中的Addtional library path,加入你的目录dll:是可实际运行的二进制代码,有定位代码的!

3、也可以在object/library中直接写上lib文件路径.(这里实际上是可以写上任意obj文件或者lib文件的).

(1).h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的。

附加依赖项的是.lib不是.dll,若生成了DLL,则肯定也生成 LIB文件。如果要完成源代码的编译和链接,有头文件和lib就够了。如果也使动态连接的程序运行起来,有dll就够了。在开发和调试阶段,当然最好都有。

.h .lib .dll三者的关系

H文件作用是:声明函数接口

DLL文件作用是: 函数可执行代码

当我们在自己的程序中引用了一个H文件里的函数,编链器怎么知道该调用哪个DLL文件呢?这就是LIB文件的作用: 告诉链接器 调用的函数在哪个DLL中,函数执行代码在DLL中的什么位置 ,这也就是为什么需要附加依赖项 .LIB文件,它起到桥梁的作用。如果生成静态库文件,则没有DLL ,只有lib,这时函数可执行代码部分也在lib文件中

目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”)。静态库是一个或者多个obj文件的打包 ,所以有人干脆把从obj文件生成lib的过程称为Archive,即合并到一起。比如你链接一个静态库,如果其中有错,它会准确的找到是哪个obj有错,即静态lib只是壳子。动态库一般会有对应的导入库,方便程序静态载入动态链接库 ,否则你可能就需要自己LoadLibary调入DLL文件,然后再手工GetProcAddress获得对应函数了。有了导入库,你只需要链接导入库后按照头文件函数接口的声明调用函数就可以了。导入库和静态库的区别很大,他们实质是不一样的东西。静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。

(2)一般的动态库程序有lib文件和dll文件。lib文件是必须在编译期就连接到应用程序中的,而dll文件是运行期才会被调用的。如果有dll文件,那么对应的lib文件一般是一些索引信息,具体的实现在dll文件中。如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。静态编译的lib文件有好处:给用户安装时就不需要再挂动态库了。但也有缺点,就是导致应用程序比较大,而且失去了动态库的灵活性,在版本升级时,同时要发布新的应用程序才行。
(3)在动态库的情况下,有两个文件,而一个是引入库(.LIB)文件,一个是DLL文件,引入库文件包含被DLL导出的函数的名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到所需要使用的DLL文件,库中的函数和数据并不复制到可执行文件中,因此在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址,这样当一个或多个应用程序运行是再把程序代码和被调用的函数代码链接起来,从而节省了内存资源。从上面的说明可以看出,DLL和.LIB文件必须随应用程序一起发行,否则应用程序将会产生错误。

 在VS2008中添加.LIB文件

法一:在project属性->链接器->输入->附加依赖项

在以上路径加入即可,多个lib名用空格隔开

 法二:直接在代码中表现:

#pragma comment(lib,"winmm.lib")   // 加入winmm.lib库

【注】以上内容均只从简单的易理解的角度阐述了各个文件的关系。若要了解详情,请参阅《程序员的自我修养——链接、装载与库》和《链接器与加载器》

转载:http://www.cnblogs.com/ShaneZhang/archive/2011/07/05/2098553.html

VC 与MATLAB接口编程方法与实现(转)

摘 要 本文简介了VC++和MATLAB特点,探讨了MATLAB与VC++接口编程的三种 方法,并详细论述了MCC和COM组件接口编程的方法和实现过程。 研究表明:采用VC++和MATLAB 接口编程方法降低了编程难度,较好地发挥了两者各自的优势。
    关键词 MATLAB;VC++;MCC;COM;接口编程

    MATLAB是美国MathWorks公司研制开发的一种 科学 计算软件,它将高性能的数值计算、符号计算和可视化集成在一起,并提供了大量的内置函数以及功能丰富的工具箱,使用方便,编程效率高。然而,MATLAB是一种解释性语言,运行效率低,不适合作为通用的编程平台。
    VC++是Microsoft公司推出的一个基于 Windows平台的可视化的集成开发环境,在运行速度、功能性以及 应用程序界面开发方面功能强大,但在数值计算和图形绘制方面,VC++并不具备太多优势。因此,采用MATLAB进行核心程序的开发,用VC++制作出友好的程序界面,然后将两者结合起来,可以较大地提高编程效率。

1 VC++与MATLAB接口方法概述

1.1 MATLAB引擎方式

    MATLAB引擎采用客户机/服务器(Client/Server) 的方式,提供了一组MATAB API函数,通过调用这些函数实现以用程序进程之间的数据传递。在运用中,让VC++程序作为前端客户机,它向MATLAB引擎传递命令和数据,并从MATLAB引擎接受数据信息,实现动态通讯。

1.2 MATLAB编译器(MCC)

    MCC是MATLAB中经过优化的编译器。使用MCC,用户可以将MATLAB数学库、图形库和界面的MATLAB程序转化为独立于MATLAB的EXE应用程序和DLL动态连接库,在VC中编写程序界面并加载调用动态连接库,实现两者之间的连接。

1.3 COM组件

    组件对象模型(简称MCR)是以组件为发布单元的对象模型。它提供一种可以共享二进制代码的 工业标准,允许任何符合标准的程序访问,所以COM作为不同语言之间的协作开发是非常方便的。MATLAB的COM编译器是在MATLAB6.5中才开始提供的一个新工具,从MATLAB7.0起,这个产品改名为MATLAB Builder for COM。基于COM的混合编程方法也是Mathworks公司推荐使用的方法。
    以上三种方法中,采用MATLAB引擎方式,应用程序整体性能好,MATLAB引擎支持功能全面,但需要MATLAB后台运行,不能脱离MALAB环境。而 MCC方法和COM组件方法均可以脱离MATLAB环境,应用程序运行效率高,利于软件的开发,本文将重点论述MCC和COM组件方法。

2 MATLAB编译器(MCC)

2.1 MATLAB与VC++接口配置

    采用MCC方法需要对MATLAB和VC++接口设置,配置步骤如下:
    1) MATLAB编译器配置
    首先在MATLAB命令提示符下输入mbuild-setup 命令,选择编译器,(需要注意的是必须确保计算机上已经安装了某个版本的VC++,本文选择visual C++6.0)完成编译器设置。
    2) VC++环境设置
    (1)设定头文件和库文件路径。在VC++环境菜单栏中选择Tools->Options->Directories,在“Show directories for”栏中首先选择Include files,然后在“directories”中将<matlab7.0安装目>\Extern\Lib\Win32\ Microsoft \MSVC++60添加进去。再次在“Show directories for”栏中选择Librarys files,再在“directories”中添加<matlab7.0安装目录>\Extern\Include。
    (2)设置编译连接选项。在VC++环境菜单栏中选择Project ->setting,然后选择link选项卡,在object/library modules栏中添加mclmcrrt.lib libtest.lib;选择General选项卡,在Microsoft Foundation Classes栏中选择Use MFC in a Shared Library。

2.2 实例演示

    完成MATLAB和VC++的接口设置以后,就可以实现MATLAB和VC++的接口编程,具体步骤如下:
    1) 编写M函数文件“mypascal.m”
    function m=mypascal(n)
    m=pascal(n);
    m=m';
    示例M函数文件的作用是生成一个n阶的帕斯卡矩阵并返回,Pascal矩阵特点:第一行和第一列的元素均为1,其他位置的元素是前方的元素和上方的元素之和。需要注意的是:由于MATLAB中矩阵存储方式是以矩阵的列为先,也就是数据从第一列开始逐列存储的,而C/C++中矩阵则是以第一行开始逐渐存储的,因此在函数的最后一行对返回矩阵取转置运算,等效于使得计算得到的矩阵数据以行模式存储。
    2) 编译M文件
    在MATLAB命令行输入mcc-B csharedlib:libtest mypascal.m-v命令(或mcc-W lib:libtest-T link:lib mypascal.m)将m文件编译成C共享动态链接库文件。命令执行完毕后,在当前目录中生成C头文件 (libtest .h) 、引入库文件 (libtest.lib) 、ctf(libtest.ctf) 文件、动态链接库文件 (libtest.dll) 、C源文件 (libtest.c)等8个文件。
    3) 创建工程对话框

    运行visual C++创建一个对话框工程,取名为test,接受所有默认的设置。去掉对话框上的静态文本和按钮,增加一个按钮、一个静态文本框、编辑框以及一个List Control,鼠标右键单击List Control,选择Properties,把View改成Report,对话框界面如图1所示。给List Control控件添加ClistCtrl类的对象m_List,给编辑框关联一个整型成员变量m_size,给按钮增加一个消息响应函数。



图 1
    4) 添加编译文件到工程
    将mcc编译生成的“libtest.h”、“libtest.dll”、“libtest.lib”,“libtest.ctf”四个文件复制到工程目录,将libtest.h加入工程,并在对话框程序文件“testDlg.cpp”中添加头文件“libtest.h”。
    5) VC++中调用动态连接库
    ① 在OnInitDialog()函数中添加初始化libtest.dll进程的码:
BOOL CTestDlg::OnInitDialog()
{
     CDialog::OnInitDialog();
     // TODO: Add extra initialization here
     if (!mclInitializeApplication(NULL,0))
     {AfxMessageBox("不能初始化程序!");exit(1);}
     if (!libtestInitialize()) {AfxMessageBox("不能初始化连接库!");exit(1);}
     return TRUE; // return TRUE unless you set the focus to a control
}
    ② 在void CTestDlg::OnCreatebuttom()函数中添加以下代码,实现对mypascal.m的调用,并将计算结果显示在对话框界面中。
void CTestDlg::OnCreatebuttom()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
double data;
data=double(m_size);
mxArray *size; //输入参数
mxArray *out=NULL; //输出参数
//创建mxArray数据对象,双精度标量
size=mxCreateDoubleScalar(data);
//内存复制赋值
memcpy(mxGetPr(size),&data,1*sizeof(double));          mlfMypascal(1,&out,size);//函数调用
//结果数据显示
CString strtext;
int i,j;
//清除已显示的数据
m_List.DeleteAllItems();
intncolumn=m_List.GetHeaderCtrl()->
GetItemCount();
for (i=0;i<ncolumn;i++) m_List.DeleteColumn(0);
//设置标题栏
m_List.InsertColumn(0," ");//附空值
m_List.SetColumnWidth(0,60);//设置每栏宽度
for (i=0;i<m_size;i++)
     {
            strtext.Format("Column %d",i+1);
            m_List.InsertColumn(i+1,strtext);
            m_List.SetColumnWidth(i+1,60);
     }
//显示结果数据
for (i=0;i<m_size;i++)
     {
            strtext.Format("Row %d",i+1);
            m_List.InsertItem(i+1,strtext);
            for(j=0;j<m_size;j++)
            {
strtext.Format("%.f",*(mxGetPr(out)+i*m_size+j));
m_List.SetItemText(i,j+1,strtext);
            }
     }
mxDestroyArray(size);//数据内存释放
mxDestroyArray(out);
}
    ③ 利用ClassWizard为对话框添加OnDestroy()函数,并添加以下代码:
void CTestDlg::OnDestroy()
{   CDialog::OnDestroy();
     // TODO: Add your message handler code her
     libtestTerminate();//终止进程
     mclTerminateApplication();//终止MCR
}
    在VC++中编译、运行结果如图2所示,与在MATLAB中运行M文件的结果一样。



图2

6) 独立应用程序的发布

发布独立的应用程序时,需要拷贝以下几个文件到目标机器上:MCRInstaller.exe,这个文件位于<matlab7.0安装目录>\tool-box\compiler\deploy\ win32目录之下,应用程序运行前要先点击运行MCRInstaller.exe文件,按照提示步骤安装好MCR,然后将工程文件的可执行程序(.exe)、共享库(.dll)以及其对应的ctf文件复制到目标 计算机即可独立运行。

3 COM组件

3.1 MATLAB里创建COM组件

    使用COM组件 方法首先需要在MATLAB中创建COM组件,步骤如下:
    1) 创建COM组件
    在MATLAB命令窗口输入命令comtool,打开Matlab Builder对话框,它是Matlab builder for com的主要工作环境。点击File->New Project,会弹出一个新工程设置对话框,填入组件名和类名,完成之后点OK,完成新工程的创建。如果选择的工程所在目录并不存在,comtool会提示该目录不存在,并询问是否创建该目录,选择Yes,comtool就会创建工程到该目录。
    2) 添加M文件到组件
    执行完第一步后回到matlab builder界面。点击刚才创建的工程,单击Add files按钮,将M文件添加到新建的组件类中。然后点击Build->COM Object编译当前工程的COM组件,这个步骤不仅编译了COM组件,同时也在计算机上注册了该组件,它可以像其他COM组件一样在VC++中使用。编译完成以后在用户设置的项目目录下将产生两个子文件夹src和distrib,src里包含组件的源代码,distrib里包含供用户最终发布使用的COM组件。
    3) 打包组件及MCR
    编译结束后产生的COM组件只能在当前计算机上使用,为了能够把它发布到其他计算机上使用,还需要其他一些支持文件。另外,COM组件不同于普通的DLL文件,COM组件必须注册后才能在计算机上使用。选择Component->package component命令,comtool将会把发布该组件所需要的所有文件打包到一个和工程同名的可执行文件中。这里可以选择是否在打包文件中包含MCR。MATLAB7.0产生的COM组件必须运行在MCR环境。如果目标计算机上没有安装MCR,那么在打包组件的时候最好选择包含MCR,这样在打包文件中就会包含MCR的安装文件。打包完成后将会在distrib中产生.exe的可执行文件,这是一个可以自解压的压缩文件。其中包含4个文件:_install.bat,dll文件,ctf文件,MCRInstaller.exe。把产生的.exe文件复制到需要发布的计算机上运行。结果将会把这四个文件解压,并执行_install.bat,这是一个DOS批处理文件,查看_install.bat的 内容后可以发现_install.bat将会运行MCRInstaller.exe来安装MCR,并且在系统中注册组件文件。

3.2 实例演示

    这里仍旧采用上例“mypascal.m”文件,按照3.1介绍的步骤创建COM组件,组件名取Tpascal,类名取Tpascalclass。运行visual C++创建一个与上例一样对话框工程,对话框设置也与上例一样。然后在MFC工程中进行如下操作:
    1) 导入DLL文件
    将distrib文件夹里Tpascal_1_0.dll拷贝到工程文件夹,然后用VC++命令#import来把Tpascal_1_0.dll导入工程中,#import命令的作用是从Tpascal_1_0.dll中导入组件中的接口类型定义,具体做法是在stdafx.h里,加入下面两行:
#import "Tpascal_1_0.dll" raw_interfaces_only
using namespace Tpascal;
    2) 为工程对话框添加实 现代
    在对话框按钮消息响应函数中编写调用组件代码:
void CTestDlg::OnCreatebutton()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
CoInitialize(NULL);       //初始化COM
//得到COM对象的CLSID      
CLSID clsid;
HRESULT hr;
hr=CLSIDFromProgID(OLESTR("Tpascal.Tpascalclass.1_0"),&clsid);
//创建一个COM对象的实例
ITpascalclass *pIpascal;
hr=CoCreateInstance(clsid,NULL,CLSCTX_INPROC_ SERVER,__uuidof(ITpascalclass),(LPVOID *) &pIpascal);
if (FAILED(hr))//测试创建是否成功
{ AfxMessageBox("create failed");
return;
}
//初始化VARIANT变量
VARIANT size,out;
VariantInit(&size);
VariantInit(&out);
//创建size,类型为VT_R8,即double型
size.vt=VT_R8;
size.dblVal=(double)m_size;
//创建二维数组out,类型为VT_ARRAY,ARRAY中的元素为double型
out.vt=VT_ARRAY|VT_R8;
SAFEARRAYBOUND bound[2];
//设置第一维数组元素个数、元素索引下界
bound[0].cElements=m_size;
bound[0].lLbound=0;
//设置第二维数组元素个数、元素索引下界
bound[1].cElements=m_size;
bound[1].lLbound=0;     out.parray=SafeArrayCreate(VT_R8,2,bound);
pIpascal->mypascal(1,&out,size); //函数调用
//返回值传递
double *matrix,* pDest;
matrix=new double[m_size*m_size];
SafeArrayAccessData(out.parray,(void**)&pDest);//获得数据指针,访问数据
memcpy(matrix,pDest,m_size*m_size*sizeof(double));// 拷贝数据矩阵
SafeArrayUnaccessData(out.parray);//释放数据指针,取消访问
SafeArrayDestroy(out.parray); //释放数组
//结果数据显示的代码与上例一样,此处省略……
delete []matrix; //释放指针
pIpascal->Release();
if(pIpascal!=NULL)
{
    pIpascal = NULL;
}
VariantClear(&size);//清空变量
VariantClear(&out);
CoUninitialize();//释放COM
}
    在VC++中编译、运行结果与上例一样,也与在MATLAB中运行M文件的结果一致。
    3) 独立程序的发布
    采用COM组件的方法的独立程序的发布,除了需要在目标计算机上运行打包组件产生的可执行文件Tpascal.exe,安装MCRInstaller.exe,并注册Tpascal_1_0.dll以外。还需要将MFC工程的可执行文件.exe拷贝到目标计算机上运行即可实现独立程序的发布。

4 结束语

    在软件开发过程中,为了提高软件的开发效率,接口编程是综合使用多种开发工具技术优势的一种常用手段。本文采用基于MCC和COM组件的VC++与MATLAB接口编程方法,具有实现简单、执行效率高、几乎支持所有的MATLAB函数、易于移植等优点,是解决矩阵处理、计算以及图像处理编程的一种有效途径,可以为 科学 研究和工程技术提供更强的技术支持。本文所有代码在环境为 Windows XP、MATLAB 7.0.1、VC++6.0下均调试通过。

 

VS2008 C++ 调用MATLAB 2010a 生成的DLL

转载:http://blog.csdn.net/infocarrier/article/details/5854522,但是还是有些修改

刚开始学习用VC++调用matlab生成的DLL,找了网上一些资料,难以找到vs2008与MATLAB20010a版本的,按照以往版本做的总是有很多错误。经过两天努力,终于调试成功,这里将经验总结一下,以供有需要的人们参考。

实验环境:

Win7

MATLAB 2010a(安装路径:E:/Program Files/MATLAB/R2009a)

VS2008 中文版(安装路径:E:/Program Files/Microsoft Visual Studio 9.0)

1.Matlab 生成DLL

1.1配置matlab

在matlab中先安装编译器,我在第一次安装的时候一路y下来,只有一个compiler,还是最老的。这教育我们要学会说N,按照以下步骤操作

>> mex -setup
Please choose your compiler for building external interface (MEX) files: 
 
Would you like mex to locate installed compilers [y]/n? y
 
Select a compiler: 
[1] Lcc-win32 C 2.4.1 in D:\PROGRA~1\MATLAB\R2010a\sys\lcc 
[2] Microsoft Visual C++ 2010 in D:\Program Files\Microsoft Visual Studio 10.0 
[3] Microsoft Visual C++ 2008 SP1 in D:\Program Files\Microsoft Visual Studio 9.0 
[4] Microsoft Visual C++ 6.0 in D:\Program Files\Microsoft Visual Studio 
 
[0] None 
 
Compiler: 3
 
Please verify your choices: 
 
Compiler: Microsoft Visual C++ 2008 SP1  
Location: D:\Program Files\Microsoft Visual Studio 9.0 
 
Are these correct [y]/n? y
 
*************************************************************************** 
  Warning: MEX-files generated using Microsoft Visual C++ 2008 require 
           that Microsoft Visual Studio 2008 run-time libraries be  
           available on the computer they are run on. 
           If you plan to redistribute your MEX-files to other MATLAB 
           users, be sure that they have the run-time libraries. 
*************************************************************************** 
 
Trying to update options file: C:\Users\Hellen\AppData\Roaming\MathWorks\MATLAB\R2010a\mexopts.bat 
From template:              D:\PROGRA~1\MATLAB\R2010a\bin\win32\mexopts\msvc90opts.bat 
 
Done . . . 
 
************************************************************************** 
  Warning: The MATLAB C and Fortran API has changed to support MATLAB 
           variables with more than 2^32-1 elements.  In the near future 
           you will be required to update your code to utilize the new 
           API. You can find more information about this at: 
           http://www.mathworks.com/support/solutions/en/data/1-5C27B9/?solution=1-5C27B9 
           Building with the -largeArrayDims option enables the new API. 
************************************************************************** 

>> mbuild -setup
Please choose your compiler for building standalone MATLAB applications: 
 
Would you like mbuild to locate installed compilers [y]/n? y
 
Select a compiler: 
[1] Lcc-win32 C 2.4.1 in D:\PROGRA~1\MATLAB\R2010a\sys\lcc 
[2] Microsoft Visual C++ 2008 SP1 in D:\Program Files\Microsoft Visual Studio 9.0 
[3] Microsoft Visual C++ 6.0 in D:\Program Files\Microsoft Visual Studio 
 
[0] None 
 
Compiler: 2
 
Please verify your choices: 
 
Compiler: Microsoft Visual C++ 2008 SP1  
Location: D:\Program Files\Microsoft Visual Studio 9.0 
 
Are these correct [y]/n? y
 
**************************************************************************** 
  Warning: Applications/components generated using Microsoft Visual Studio   
           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\Hellen\AppData\Roaming\MathWorks\MATLAB\R2010a\compopts.bat 
From template:              D:\PROGRA~1\MATLAB\R2010a\bin\win32\mbuildopts\msvc90compp.bat 
 
Done . . . 

 

1.2 DLL的生成

首先新建一个m文件,文件名为myadd2.m,定义了一个名为myadd2的函数,代码如下:

//

function [y,z] = myadd2(a, b)
% dummy function, just to demonstrate the idea
y = a+b;
z = a+2*b;
end

/

在MATLAB命令框中输入以下命令:


>> mcc -W cpplib:libmyadd2 -T link:lib myadd2.m

 

生成libmyadd2.lib, libmyadd2.h, libmyadd2.dll 等文件,将这三个文件拷到VS的项目目录下

 

2. VS调用DLL

2.1 新建一个项目,并设置环境

新建一个win32 控制台应用程序,我取的名字是matlabDll.当然新建其他的项目类型也可以,我这只是个例子。接下来进行配置,在该项目的属性中进行了配置,只对该项目有效。若建新的项目需要重新配置。项目建好后将libmyadd2.lib, libmyadd2.h, libmyadd2.dll拷贝到项目目录下。

首先配置项目属性页/配置属性/C-C++/常规/附加包含目录,请根据自己电脑上软件的安装位置对照设置,2008与2005不同的地方时这里要加两个目录,如下图所示:

其次配置项目属性页/配置属性/链接器/常规/附加库目录,请根据自己电脑上软件的安装位置对照设置,如下图所示:

然后配置项目属性页/配置属性/链接器/输入/附加依赖性,填入libmyadd2.lib mclmcrrt.lib mclmcr.lib ,如下图所示:

在这一步俺可吃了大苦头了,有篇文档只说添加前两项,俺就照做了,结果导致运行失败,找了好长时间也没发现错误,两天的功夫都在找,结果就是因为少填了这一项,还有其他的一些包含lib,比如libmex.lib  libmx.lib ,这里没填,好像是VC6上要配的。

配置到此结束

注意,其实mclmcrrt.lib也是没用要!!

2.2 编写主程序,调试运行

这段代码是从别处拷来的,是一段完整代码,将它粘到matlabDLL2.cpp 主CPP文件中,调试通过:

  1. #include <iostream>   
  2. //#include "mclmcr.h"   
  3. //#include "mclcppclass.h"   
  4. #include "libmyadd2.h"   
  5.   
  6. #pragma comment(lib, "libmyadd2.lib")     
  7. #pragma comment(lib, "mclmcrrt.lib")    
  8.   
  9. int main()  
  10. {  
  11.   
  12.         std::cout << "Hello world!" << std::endl;  
  13.         /* Initialize the MCR */   
  14.         /* if( !mclInitializeApplication(NULL,0) )  
  15.         {   
  16.                 std::cout << "Could not initialize the application!" << std::endl; 
  17.                 return -1;  
  18.         } */  
  19.   
  20.         // initialize lib   
  21.         if( !libmyadd2Initialize())  
  22.         {  
  23.                 std::cout << "Could not initialize libmyadd2!" << std::endl;  
  24.                 return -1;   
  25.         }  
  26.   
  27.         try  
  28.         {  
  29.         // declare and initialize a   
  30.         mwArray a(2, 2,  mxDOUBLE_CLASS);  
  31.         double *aData;  
  32.         aData = new double[4];  
  33.         int i;  
  34.         for( i=0; i<4; ++i)  
  35.         {  
  36.                 aData[i] = 1.0*i;  
  37.         }  
  38.         // print output   
  39.         std::cout << "a = " << std::endl;  
  40.         std::cout << aData[0] << ",/t" << aData[1] << std::endl;  
  41.         std::cout << aData[2] << ",/t" << aData[3] << std::endl;  
  42.   
  43.         a.SetData(aData, 4);  
  44.   
  45.         // declare and initialize b   
  46.         mwArray b(2, 2,  mxDOUBLE_CLASS);  
  47.         b(1,1) = 11.;  
  48.         b(1,2) = 12.;  
  49.         b(2,1) = 21.;  
  50.         b(2,2) = 22.;  
  51.   
  52.         mwArray y(2, 2,  mxDOUBLE_CLASS);  
  53.         mwArray z(2, 2,  mxDOUBLE_CLASS);  
  54.   
  55.         // call the function   
  56.                 myadd2(2, y, z, a, b);  
  57.   
  58.         // copy data from mwArray to C++ objects   
  59.   
  60.         // allocate outputs   
  61.         double *yData, *zData;  
  62.         yData = new double[4];  
  63.         if( yData == NULL )  
  64.         {  
  65.                 std::cout << "Failed to allocate memory for yData!" << std::endl;  
  66.                 return -1;  
  67.         }  
  68.   
  69.         zData = new double[4];  
  70.         if( zData == NULL )  
  71.         {  
  72.                 std::cout << "Failed to allocate memory for zData!" << std::endl;  
  73.                 return -1;  
  74.         }  
  75.   
  76.         // copy data from mwArray to C++   
  77.         y.GetData(yData, 4);  
  78.         z.GetData(zData, 4);  
  79.   
  80.         // print output   
  81.         std::cout << "y = " << std::endl;  
  82.         std::cout << yData[0] << ",/t" << yData[1] << std::endl;  
  83.         std::cout << yData[2] << ",/t" << yData[3] << std::endl;  
  84.   
  85.         std::cout << "z = " << std::endl;  
  86.         std::cout << zData[0] << ",/t" << zData[1] << std::endl;  
  87.         std::cout << zData[2] << ",/t" << zData[3] << std::endl;  
  88.   
  89.           
  90.         // deallocate memory   
  91.         delete [] aData;  
  92.         delete [] zData;  
  93.         delete [] yData;  
  94.         }  
  95.         catchconst mwException& e)  
  96.         {  
  97.           std::cerr << e.what() << std::endl;  
  98.                     
  99.         }  
  100.         // terminate the lib   
  101.         libmyadd2Terminate();  
  102.   
  103.         // terminate MCR   
  104.         mclTerminateApplication();  
  105.   
  106.   
  107.         return 0;  
  108. }  
#include <iostream>
//#include "mclmcr.h"
//#include "mclcppclass.h"
#include "libmyadd2.h"

#pragma comment(lib, "libmyadd2.lib")  
#pragma comment(lib, "mclmcrrt.lib") 

int main()
{

        std::cout << "Hello world!" << std::endl;
        /* Initialize the MCR */ 
        /* if( !mclInitializeApplication(NULL,0) ) 
        {  
                std::cout << "Could not initialize the application!" << std::endl;
                return -1; 
        } */

        // initialize lib
        if( !libmyadd2Initialize())
        {
                std::cout << "Could not initialize libmyadd2!" << std::endl;
                return -1; 
        }

        try
        {
        // declare and initialize a
        mwArray a(2, 2,  mxDOUBLE_CLASS);
        double *aData;
        aData = new double[4];
        int i;
        for( i=0; i<4; ++i)
        {
                aData[i] = 1.0*i;
        }
        // print output
        std::cout << "a = " << std::endl;
        std::cout << aData[0] << ",/t" << aData[1] << std::endl;
        std::cout << aData[2] << ",/t" << aData[3] << std::endl;

        a.SetData(aData, 4);

        // declare and initialize b
        mwArray b(2, 2,  mxDOUBLE_CLASS);
        b(1,1) = 11.;
        b(1,2) = 12.;
        b(2,1) = 21.;
        b(2,2) = 22.;

        mwArray y(2, 2,  mxDOUBLE_CLASS);
        mwArray z(2, 2,  mxDOUBLE_CLASS);

        // call the function
                myadd2(2, y, z, a, b);

        // copy data from mwArray to C++ objects

        // allocate outputs
        double *yData, *zData;
        yData = new double[4];
        if( yData == NULL )
        {
                std::cout << "Failed to allocate memory for yData!" << std::endl;
                return -1;
        }

        zData = new double[4];
        if( zData == NULL )
        {
                std::cout << "Failed to allocate memory for zData!" << std::endl;
                return -1;
        }

        // copy data from mwArray to C++
        y.GetData(yData, 4);
        z.GetData(zData, 4);

        // print output
        std::cout << "y = " << std::endl;
        std::cout << yData[0] << ",/t" << yData[1] << std::endl;
        std::cout << yData[2] << ",/t" << yData[3] << std::endl;

        std::cout << "z = " << std::endl;
        std::cout << zData[0] << ",/t" << zData[1] << std::endl;
        std::cout << zData[2] << ",/t" << zData[3] << std::endl;

        
        // deallocate memory
        delete [] aData;
        delete [] zData;
        delete [] yData;
        }
        catch( const mwException& e)
        {
          std::cerr << e.what() << std::endl;
                  
        }
        // terminate the lib
        libmyadd2Terminate();

        // terminate MCR
        mclTerminateApplication();


        return 0;
}


运行结果如下图:



 

问题

我将代码的标红部分注释掉了,否则会出现错误:

1>c:/users/administrator/documents/visual studio 2008/projects/matlabdll2/matlabdll2/matlabdll2.cpp(14) : error C3861: “mclInitializeApplication_proxy”: 找不到标识符

我不知道为什么,大家在调试的过程如果解决了这个问题,麻烦告诉一声:liufengjk_ok@126.com

致谢

感谢taohe等网友提供的参考!

 

matlab2010 + vc6.0混合编程实例(调用dll)

在对matlab配置后,上代码mcc -W cpplib:libMyAdd -T link:lib MyAdd -C就可以了,记得加上-C

在对VC6.0进行配置的时候只要把 matlabroot\extern\include和matlabroot\extern\lib\win32\microsoft加入到VC6.0中去了,i.e.可以通过Tools->Options->Directories->show directories for 中的Include files和library files添加路径;

  1. #include "libMyAdd.h"   
  2.   
  3. #pragma comment(lib, "libMyAdd.lib")   
  4. #pragma comment(lib, "mclmcrrt.lib")   
  5.   
  6. using std::cout;  
  7. using std::cin;  
  8. using std::endl;  
  9.   
  10. int main(void)  
  11. {  
  12.     double a = 0;  
  13.     double b = 0;  
  14.     double c = 0;  
  15.   
  16.     // initialize lib    
  17.     if( !libMyAddInitialize())  
  18.     {  
  19.         cout << "Could not initialize libMyAdd!" << endl;  
  20.   
  21.         return -1;  
  22.     }  
  23.   
  24.     cout << "input a: ";  
  25.     cin >> a;  
  26.     cout << "\ninput b: ";  
  27.     cin >> b;  
  28.   
  29.     //为变量分配内存空间   
  30.     mwArray mwA(1, 1, mxDOUBLE_CLASS);  //1,1表示矩阵的大小(所有matlab只有一种变量,就是矩阵,   
  31.     //为了和CPP变量接轨,设置1*1的矩阵,mxDOUBLE_CLASS表示变量的精度   
  32.     mwArray mwB(1, 1, mxDOUBLE_CLASS);  
  33.     mwArray mwC(1, 1, mxDOUBLE_CLASS);  
  34.   
  35.     //调用SetData函数赋值   
  36.     mwA.SetData(&a,1);  
  37.     mwB.SetData(&b,1);  
  38.   
  39.     //调用自己写的函数MyAdd   
  40.     MyAdd(1, mwC, mwA, mwB);  
  41.   
  42.     //调用Get函数获取函数返回值   
  43.     c = mwC.Get(1,1);  
  44.   
  45.     cout << "c is " << c << endl;  
  46.   
  47.     //后面一些终止调用程序   
  48.     libMyAddTerminate();  
  49.       
  50.     mclTerminateApplication();  
  51.       
  52.     return 0;  
  53. }  
#include "libMyAdd.h"

#pragma comment(lib, "libMyAdd.lib")
#pragma comment(lib, "mclmcrrt.lib")

using std::cout;
using std::cin;
using std::endl;

int main(void)
{
	double a = 0;
	double b = 0;
	double c = 0;

	// initialize lib 
	if( !libMyAddInitialize())
	{
		cout << "Could not initialize libMyAdd!" << endl;

		return -1;
	}

	cout << "input a: ";
	cin >> a;
	cout << "\ninput b: ";
	cin >> b;

	//为变量分配内存空间
	mwArray mwA(1, 1, mxDOUBLE_CLASS);	//1,1表示矩阵的大小(所有matlab只有一种变量,就是矩阵,
	//为了和CPP变量接轨,设置1*1的矩阵,mxDOUBLE_CLASS表示变量的精度
	mwArray mwB(1, 1, mxDOUBLE_CLASS);
	mwArray mwC(1, 1, mxDOUBLE_CLASS);

	//调用SetData函数赋值
	mwA.SetData(&a,1);
	mwB.SetData(&b,1);

	//调用自己写的函数MyAdd
	MyAdd(1, mwC, mwA, mwB);

	//调用Get函数获取函数返回值
	c = mwC.Get(1,1);

	cout << "c is " << c << endl;

	//后面一些终止调用程序
	libMyAddTerminate();
	
	mclTerminateApplication();
	
	return 0;
}


运行结果:



 

 

 

 

 

 

 

 

 

 

使用VC6.0中的新建一个Win32 Dynamic-Link Library类型的工程,工程名为:dll,创建一个空的动态链接库工程,然后再工程中添加C++源文件:dll.cpp以及头文件:dll.h,在头文件以及源文件中输入下面的代码:

dll头文件:

dll.h

  1. #ifndef DLL1_API   
  2.     #define DLL1_API _declspec(dllexport)    
  3. #endif   
  4.   
  5. DLL1_API int processSaliency(char *filename, char *old_path, char *new_path);  
#ifndef DLL1_API
	#define DLL1_API _declspec(dllexport) 
#endif

DLL1_API int processSaliency(char *filename, char *old_path, char *new_path);

dll的生成步骤:

要生成的函数:

dll.cpp

  1. #define DLL1_API _declspec(dllexport)   
  2. #include "egt_saliency.h"   
  3. #include <iostream>    
  4. #include "saliency.h"    
  5.   
  6. #pragma comment(lib, "saliency.lib")     
  7. #pragma comment(lib, "mclmcrrt.lib")     
  8.   
  9. using std::cout;    
  10. using std::cin;    
  11. using std::endl;   
  12.   
  13. int processSaliency(char *filename, char *old_path, char *new_path)  
  14. {  
  15.     // initialize lib      
  16.     if( !saliencyInitialize())    
  17.     {    
  18.         cout << "Could not initialize Saliency!" << endl;    
  19.     
  20.         return -1;    
  21.     }  
  22.   
  23.     gbvs_main(filename, old_path, new_path);  
  24.      
  25.     saliencyTerminate();    
  26.         
  27.     mclTerminateApplication();  
  28.       
  29.     return 0;  
  30. }  
#define DLL1_API _declspec(dllexport)
#include "egt_saliency.h"
#include <iostream> 
#include "saliency.h" 

#pragma comment(lib, "saliency.lib")  
#pragma comment(lib, "mclmcrrt.lib")  

using std::cout;  
using std::cin;  
using std::endl; 

int processSaliency(char *filename, char *old_path, char *new_path)
{
	// initialize lib   
    if( !saliencyInitialize())  
    {  
        cout << "Could not initialize Saliency!" << endl;  
  
        return -1;  
    }

	gbvs_main(filename, old_path, new_path);
   
    saliencyTerminate();  
      
    mclTerminateApplication();
	
	return 0;
}


最后编译,在工程中会生成:dll.dll和dll.lib这两个文件;在测试程序中,需要将dll.dll、dll.lib和dll.h这三个文件一起拷贝到测试程序的工程中,这样测试程序就可以利用dll来调用函数了。
  • 1
    点赞
  • 0
    评论
  • 7
    收藏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值