posts - 112, comments - 215, trackbacks - 0, articles - 34
  IT博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

VC6调用matlab7里的m程序的案例及方法

Posted on 2006-12-02 20:14 济公 阅读(4297) 评论(11)  编辑 收藏 引用 所属分类: VCMatlab
VC + MATLAB7 C Shared Library
所有调用 MATLAB7 Compiler 产生的共享库的程序都具有如下的大致结构:

1
声明变量或者是函数作为输入变量;
2
调用 mclInitalizeApplication 函数,并测试是否成功,该函数设置了一个全局的 MCR 状态,并且构建 MCR 实例;
3
对于每个库,调用一次 <libraryname>Initalize 函数,为库创建一个 MCR 实例;
4
调用库中的函数,并处理其结果(这是程序的主要部分);
5
为每个库调用一次 <libraryname>Terminate 函数,用于注销相联系的 MCR
6
调用 mclTerminateApplication 函数,释放与全局 MCR 状态相联系的资源;
7
清除变换,关闭文件等,然后退出。
根据 MATLAB 的帮助文档中提供的例子,利用如下文件进行练习:
<matlabroot>/extern/examples/compiler/addmatrix.m
<matlabroot>/extern/examples/compiler/multiplymatrix.m
<matlabroot>/extern/examples/compiler/eigmatrix.m
实现步骤:
1
先将这几个文件拷贝到当前目录下,然后利用 mcc 创建共享库,指令如下:
mcc –v -B csharedlib:libmatrix addmatrix.m multiplymatrix.m eigmatrix.m
其中,操作参数 -B csharedlib 是一个绑定的操作,其等效指令为 -W lib:<libname> -T link:lib
2
)在 VC 中创建一个 MFC 工程(本人创建的为基于对话框的),环境设置根据如下帖子: 怎样设置  Visual Studio   Matlb Complier 4.0  一起工作   中的指导进行。在本例子中,只需要在 VC 中进行如下步骤:
A. Tools->Options->Directories->Show directories for
Include files-><matlab7root> \Extern\Include
B. Tools->Options->Directories->Show directories for
Library files-><matlab7root> \Extern\Lib\Win32\Microsoft\msvc60
C. Project->Setting->C/C++->Category
Code Generation->Use run-time library Debug Multithread DLL
D. Project->Setting->Link->Category
Input->Object/library modules mclmcrrt.lib libmatrix.lib mcc 生成的共享库)。
3
)拷贝 MATLAB 当前目录下刚才用 mcc 生成的 libmatrix.h libmatrix.dll libmatrix.lib ,以及 libmatrix.ctf 文件到 VC 当前工程目录下,并用 Project->Add to Project->Files… libmatrix.h 加入到当前工程中。
4
)在当前工程的对话框的头文件中加入 #include "libmatrix.h" #include "mclmcr.h"
5
)在 BOOL CMatlab7dllDlg::OnInitDialog() 中进行 MATLAB 库文件的初始化,在 void CMatlab7dllDlg::OnDestroy() 中进行 MATLAB 库文件资源的释放,否则可能出现按钮只能够按一次,第二次运行则出错的现象;
6
)调用 MATLAB 产生的库文件中函数的处理函数定义在一个按钮的响应函数中,并且要注意的是:如果一个 mxArray 变量需要重用的时候,必须用 mxDestroyArray(out); out=0; 即先进行变量注销,再设置为空。
附上这几个主要函数如下:
1
BOOL CMatlab7dllDlg::OnInitDialog()
{
   CDialog::OnInitDialog();
    ……………
    // TODO: Add extra initialization here
   /* Call the mclInitializeApplication routine. Make sure that the application
    * was initialized properly by checking the return status. This initialization
    * has to be done before calling any MATLAB API's or MATLAB Compiler generated
    * shared library functions.  */
   if( !mclInitializeApplication(NULL,0) )
   {
       AfxMessageBox( "Could not initialize the application.");
       exit(1);
   }
   /* Call the library intialization routine and make sure that the
    * library was initialized properly. */
   if (!libmatrixInitialize())
   {
       AfxMessageBox("Could not initialize the library.");
       exit(1);
   }
return TRUE;  // return TRUE  unless you set the focus to a control
}

2
void CMatlab7dllDlg::OnDestroy()
{
CDialog::OnDestroy();
/* Call the library termination routine */
libmatrixTerminate();
 mclTerminateApplication();
}

3
void CMatlab7dllDlg::OnRUN()
{
CString str;
mxArray *in1, *in2; /* Define input parameters */
   mxArray *out = NULL;/* and output parameters to be passed to the library functions */
   
   double data[] = {1,2,3,4,5,6,7,8,9};

   /* Create the input data */
   in1 = mxCreateDoubleMatrix(3,3,mxREAL);
   in2 = mxCreateDoubleMatrix(3,3,mxREAL);
   
memcpy(mxGetPr(in1), data, 9*sizeof(double));
   memcpy(mxGetPr(in2), data, 9*sizeof(double));
  
   /* Call the library function */
   mlfAddmatrix(1, &out, in1, in2);
   /* Display the return value of the library function */
   str="The value of added matrix is:\n";
str = str + Display(out);
AfxMessageBox(str);

   /* Destroy the return value since this varaible will be resued in
    * the next function call. Since we are going to reuse the variable,
    * we have to set it to NULL. Refer to MATLAB Compiler documentation
    * for more information on this. */
mxDestroyArray(out); out=0;

   mlfMultiplymatrix(1, &out, in1, in2);
   str = "The value of the multiplied matrix is:\n";
str = str+Display(out);
AfxMessageBox(str);

mxDestroyArray(out); out=0;

   mlfEigmatrix(1, &out, in1);
   str = "The Eigen value of the first matrix is:\n";
str = str+Display(out);
AfxMessageBox(str);

   mxDestroyArray(out); out=0;
   /* Free the memory created */
   mxDestroyArray(in1); in1=0;
   mxDestroyArray(in2); in2 = 0;

AfxMessageBox("OK, Finished!");
}

4
CString CMatlab7dllDlg::Display(const mxArray *in)
{
 CString str, strout=" ";
   int i=0, j=0; /* loop index variables */
   int r=0, c=0; /* variables to store the row and column length of the matrix */
   double *data; /* variable to point to the double data stored within the mxArray */
   /* Get the size of the matrix */
   r = mxGetM(in);
   c = mxGetN(in);
   /* Get a pointer to the double data in mxArray */
   data = mxGetPr(in);
     /* Loop through the data and display the same in matrix format */
   for( i = 0; i < c; i++ ){
       for( j = 0; j < r; j++){
           str.Format("%4.2f\t",data[i*c+j]);
strout = strout+str;
       }
       strout = strout+"\n";
   }
   strout = strout +"\n";
return strout;
}

5
.附 m 文件:

1
addmatrix.m
function a = addmatrix(a1, a2)
%ADDMATRIX Add two matrices
% Copyright 2003 The MathWorks, Inc.
a = a1 + a2;

2) multiplymatrix.m
function m = multiplymatrix(a1, a2)
%MULTIPLYMATRIX Multiplies two matrices
% Copyright 2003 The MathWorks, Inc.
m =  a1*a2;

3) eigmatrix.m
function e = eigmatrix(a1)
%EIGMATRIX Returns the eigen value of the given matrix
% Copyright 2003 The MathWorks, Inc.
e = eig(a1);

发布到目标机器上的时候需要拷贝过去的文件有: MCRInstaller.exe ,工程文件的可执行程序,共享库 (DLL) ,共享库对应的 .ctf 文件。点击运行 MCRInstaller.exe 文件,安装好 MCR 之后,将 <mcr_root>\runtime\win32 加入到系统的环境变量 path 中去

Feedback

# re: VC6调用matlab7里的m程序的案例及方法  回复  更多评论   

2007-05-16 13:45 by Favory
兄弟这篇文章很好,谢谢啦!

# re: VC6调用matlab7里的m程序的案例及方法  回复  更多评论   

2007-06-06 20:11 by feiyeying
请问一下,我在matlabR2006b下按照您这篇文章操作,到VC编译通过后总是说“Could not initialize the library.“(libmatrixInitialize()那部分),因为是初次尝试混编,实在不明白自己那里做错了,望您能指点一下,谢谢

# re: VC6调用matlab7里的m程序的案例及方法  回复  更多评论   

2007-06-07 09:36 by 济公
TO:feiyeying
你用7.0吧

# re: VC6调用matlab7里的m程序的案例及方法  回复  更多评论   

2007-06-16 21:50 by const
我用的是7.0,也出现了“Could not initialize the library.“的问题

# re: VC6调用matlab7里的m程序的案例及方法  回复  更多评论   

2007-07-29 03:03 by weiwei
我的是7.0,还没出Could not initialize the library,运行时直接就是说出现问题,程序需要关闭,我在libmatrixInitialize()处放断点调试,一执行这句就弹出对话框 unhandled exception in ***.exe :0XC0000005 :Acceess violation.
请问有人知道什么原因么?

急啊!

# re: VC6调用matlab7里的m程序的案例及方法  回复  更多评论   

2007-08-08 17:55 by 老牛
那位知道libmatrixInitialize()初始化失败的原因?谢谢

# re: VC6调用matlab7里的m程序的案例及方法  回复  更多评论   

2007-12-03 16:55 by yt
我的是7.1,

# re: VC6调用matlab7里的m程序的案例及方法  回复  更多评论   

2007-12-03 16:59 by yt
我的是7.1,完全按上面的方法进行。但编译时出现
'mlfAddmatrix' : undeclared identifier
C:\Documents and Settings\Administrator\桌面\ytexamp\ytexampDlg.cpp(221) : error C2065: 'mlfMultiplymatrix' : undeclared identifier
C:\Documents and Settings\Administrator\桌面\ytexamp\ytexampDlg.cpp(229) : error C2065: 'mlfEigmatrix' : undeclared identifier
Error executing cl.exe.

ytexampDlg.obj - 3 error(s), 0 warning(s)
为什么?

# re: VC6调用matlab7里的m程序的案例及方法  回复  更多评论   

2007-12-03 17:05 by yt
查看libmatrix.h头文件后,将上述三个函数该为 头中定义如下:LIB_libmatrix_CPP_API void addmatrix(int nargout, mwArray& a
, const mwArray& a1
, const mwArray& a2);

extern LIB_libmatrix_CPP_API void multiplymatrix(int nargout, mwArray& m
, const mwArray& a1
, const mwArray& a2);

extern LIB_libmatrix_CPP_API void eigmatrix(int nargout, mwArray& e
, const mwArray& a1);
改为直接调用后出现\Documents and Settings\Administrator\桌面\ytexamp\ytexampDlg.cpp(206) : error C2664: 'addmatrix' : cannot convert parameter 2 from 'struct mxArray_tag *' to 'class mwArray
请教大虾?

# re: VC6调用matlab7里的m程序的案例及方法  回复  更多评论   

2007-12-04 15:51 by 济公
TO:yt
我长时间没有用这东西,我现在电脑上也没装Matlab,没法给你测试。上面说的还算比较清楚,你好好调试下,看看环境的设置搞好了没有等。

# re: VC6调用matlab7里的m程序的案例及方法  回复  更多评论   

2008-03-13 20:46 by fly
很好,支持,环境变量要配置好,不要和其他的程序发生冲突
我的和IBM的DB2下面的dll发生了冲突,给了好大的劲才搞好了,大家以后要注意啊
只有注册用户登录后才能发表评论。