注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

投资参考月刊 投资家信息平台

中国经济理论及环境研究会

 
 
 

日志

 
 
关于我

江苏南京,南京大学毕业,哲学学者,经济学者,财经评论员,投资参考月刊编辑,中国经济理论及环境研究会会员。提出了物质认识论新哲学理论。2007年首先短临预测了A股、国际油价大调整,随后提出了货币经济中预期收益率货币流动原理,在货币经济理论体系中得到很大反响与应用,该理论已被中国证券教科书收录。

在VC中做matlab com组件的方法  

2010-07-27 10:10:23|  分类: 杂谈 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

1. 首先,设置合适的编译器。在MATLAB命令窗口里敲:mbuild –setup 和 mex –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 C version 2.4 in C:\MATLAB7\sys\lcc
[2] Microsoft Visual C/C++ version 6.0 in C:\Program Files\Microsoft Visual Studio
[0] None

Compiler: 2

● Please verify your choices:
Compiler: Microsoft Visual C/C++ 6.0
Location: C:\Program Files\Microsoft Visual Studio
Are these correct?([y]/n): y

● Try to update options file: C:\Documents and Settings\Administrator\Application Data\MathWorks\MATLAB\R14\compopts.bat
From template: C:\MATLAB7\BIN\WIN32\mbuildopts\msvc60compp.bat
Done . . .
--> "C:\MATLAB7\bin\win32\mwregsvr C:\MATLAB7\bin\win32\mwcomutil.dll"
DllRegisterServer in C:\MATLAB7\bin\win32\mwcomutil.dll succeeded
--> "C:\MATLAB7\bin\win32\mwregsvr C:\MATLAB7\bin\win32\mwcommgr.dll"
DllRegisterServer in C:\MATLAB7\bin\win32\mwcommgr.dll succeeded

● 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] Digital Visual Fortran version 6.0 in C:\Program Files\Microsoft Visual Studio
[2] Lcc C version 2.4 in C:\MATLAB7\sys\lcc
[3] Microsoft Visual C/C++ version 6.0 in C:\Program Files\Microsoft Visual Studio
[0] None
Compiler: 3

● Please verify your choices:
Compiler: Microsoft Visual C/C++ 6.0
Location: C:\Program Files\Microsoft Visual Studio
Are these correct?([y]/n): y

Try to update options file: C:\Documents and Settings\Administrator\Application Data\MathWorks\MATLAB\R14\mexopts.bat
From template: C:\MATLAB7\BIN\WIN32\mexopts\msvc60opts.bat

Done . . .

2. 设置系统路径。我的电脑->属性->高级->环境变量->系统变量->Path选项,增加以下路径:
头文件:
C:\MATLAB7\extern\include;
库:
C:\MATLAB7\extern\lib\win32\microsoft\msvc60;
DLL:
C:\MATLAB7\bin\win32

3. 做一个简单的M函数(只能是函数不能是文件)。文件名和函数名一致。运行并测试此文件的正确性。
function plot_test(result)
plot(result); %画图

4. 在命令窗口敲comtool,出现com组件builder。选择FILE选项->New Project选项。出现以下界面。

Component name选项:设置com组件的名称,注意不要和上面添加的m文件重名。
Class name选项:设置类名称。一般将鼠标点击空白位置,系统会自动生成类名。
Project version选项:版本号。系统默认为1.0,将来要修改或添加其他函数时,可以修改此选项为2.0,3.0等。
Project directory选项:工程所在目录。
Complier options选项:编译器配置选项,全部选中。
最后单击OK。系统会出现对话框,问你是否创立工程目录,你选YES。

5. 单击Project Files->plotclass->M-files,然后选中comtool菜单Project->Add File选项,添加上面写好的plot_test M函数,如下图:

当然,你可以添加更多的M或MEX函数。

6. 单击Build按钮,选中Com Object选项,这时com-builder会帮你自动编译连接该组件,生成所需要的头文件,源文件,接口描述文件,动态连接库文件,等等。在右侧Build Status显示框里给出了编译的过程和信息。在菜单Component->Component Info里有关于接口、类、库的信息。在C:\MATLAB7\work\plot文件夹里,出现了两个子文件夹,distrib和src,这是我们VC中需要用到的文件、库、资源、接口等。在src-> plot_idl_i.c中,有关于com类和com接口的GUID。其中CLSID(类的GUID)在VC编程中需要用到。

7. 打开VC++编译器,选择文件->新建->工程->MFC(exe)->命名(plot)->单文档->完成。我们在资源Toolbar里建立两个按钮,一个用于启动COM(OLE),获得接口指针;另一个用于调用绘图(plot_test)命令。用查看->类向导建立,在CplotView类里建立command消息映射。

8. 再次打开类向导,在 Add Class选项内,选中From a typed library,进入C:\MATLAB7\work\plot\src文件夹,选中plot_idl.tlb文件,点击打开?OK。

这时一个COM类便加入进来了,查看一下Iplotclass类。里面有些,我们想要的东东。
9. 下面就是OLE调用的基本方法了,具体可以参见MSDN。
首先在CplotApp类的InitInstance()里添加初始化OLE代码。
BOOL suc=AfxOleInit(); // 初始化OLE
if (suc==FALSE)
{
::AfxMessageBox("初始化OLE失败!");
}

其次,在CplotView里包含plot_idl.h,math.h头文件,并定义常量PI;并从C:\MATLAB7\work\plot\src\plot_idl_i.c中拷贝类的GUID并复制到PlotView.h文件类定义的上面。
#include "plot_idl.h"
#include "math.h"
#define PI 3.1415926535897

const CLSID CLSID_plotclass = {0xAED07AAF,0x3190,0x4996,{0xAD,0xD6,0x31,0xF9,0x45,0x41,0xB1,0xC5};

再次在构造函数CPlotView()的上面定义类全局对象;
Iplotclass plot;

然后,OnStart()函数里添加获得COM指针的函数,代码如下:
plot.CreateDispatch(CLSID_plotclass,NULL); //创立接口
COleDispatchDriver(); //连接(此句可以不写)

然后,在OnPlot()函数里添加绘图代码,代码如下,这里关于VARIANT变量的用法说明请参照MSDN。

const int N=100; //数组大小
double a[N]; //数组定义
double f=50; //正弦信号频率
double Ts=0.002; //采样时间

// 赋值
for (int i=0; i<N; i++)
{
a[i]=sin(2*PI*f*i*Ts);
}

//任意变量
VARIANT x;
VariantInit(&x); //初始化

x.vt=VT_ARRAY|VT_R8; //类型(数组,双精度型)

SAFEARRAYBOUND rgsabound[1];
rgsabound[0].cElements=N; //数组所含元素数
rgsabound[0].lLbound=0; //数组上界

//创立数组
x.parray=SafeArrayCreate(VT_R8,1,rgsabound); //创立一维数组

//锁定数组
SafeArrayLock(x.parray);

//数组传递数据
x.parray->pvData=a;


//调用方法
plot.plot_test(x);

//解锁
SafeArrayUnlock(x.parray);

最后,在析构函数~CPlotView()里添加释放接口和资源的代码。
plot.DetachDispatch();

10. 测试。先按绿色按钮,初始化OLE和接口,再按红色按钮绘图。注意,开始绿色按扭,比较慢,因为要载入很多DLL,后面红色按钮就快多了,并且第二次执行会更快。现在是不是感到很爽呢?别急,还有最后一步打包发布。还要注意的是,最好再做个程序,防止多次按下绿色按扭,否则会有错误。当关闭窗口时,所有载入的资源会自动释放。

11. 打包。再次打开,原来的工程文件*.cbl,注意在前面过程中一定要保存。(matlab会有提示)。然后选择Component->Package Component,系统就会自己帮你打包了。出现如下图,选中Include MCR,点击Create选项。慢慢等吧。

打包完毕后,在C:\MATLAB7\work\plot\distrib文件夹下,有plot可执行文件。拷贝C:\MATLAB7\work\plot文件夹下所有文件,在另外一个机器上,双击plot可执行程序,注册com组件,就完成了最后的工作。你的程序,就可以在其他机器上执行了。(这一点,还值得研究,能否自己打包,不用matlab工具呢?plot的执行界面是基于DOS的,很丑)。

备注:comtool工具6.5版本后才有,所以那些老版本的朋友们只有望com而心憾了。

 

com组件的使用
///////////////////////////////////////////////////////

copy  iir_1_0.c\iir_1_0.h\iir_1_0.dll\mwcomutil.h\mwcomtypes.h\文件至工程目录下

加入.c、.h文件
在dzku.cpp 与 dzkuview.cpp加入如下

#import "mwcomutil.dll"
#import "iir_1_0.dll"
#include "mwcomutil.h"
#include "iir_1_0.h"

如果dzkuview.cpp先加入上面的头文件再加入下面的函数,编译连接时可能出错,这时先把上面的语句删掉,载编译
,然后再加入上面语句,再编译,就可通过

编译时将project-->setting-->c/c++-->category-->precompiled headers设置为automatic use of precompiled headers
debug 与release模式下皆要设置如上

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

本人所写的一个例子:

初始化com
BOOL CDzkuView::PreCreateWindow(CREATESTRUCT& cs)
{
 // TODO: Add your specialized code here and/or call the base class
 if (FAILED(CoInitialize(NULL)))
  {
    AfxMessageBox("unable to initialize COM");
}

HRESULT hr=CoCreateInstance(CLSID_hh, NULL,CLSCTX_ALL,IID_Ihh,(void**)&glf);

  if (SUCCEEDED(hr))
  {
   
   AfxMessageBox("成功初始化Matlab COM组件");
  
}
else
  {
   AfxMessageBox("不能装载Matlab COM组件!");
} /* */ 
 return CView::PreCreateWindow(cs);
}


//////////////////////////////////////////////////函数调用com组件的函数(仿真763调用glf->irr_low)
void CDzkuView::On763()
{
 
CDzkuDoc* doc=GetDocument();//DO: Add your command handler code here
long N;
N=doc->total_sec*50;
HRESULT hr;
 SAFEARRAYBOUND rgsabound[1];
 rgsabound[0].lLbound = 0;  //The first (and only) collumn of our array starts at 0.
 rgsabound[0].cElements = N; //and has 100 elements.
 
 //create the array
 VARIANT  y;
VariantInit(&y);
double * bb;
 VARIANT myVariant;
 SAFEARRAY FAR* pMySafeArray;
 pMySafeArray = SafeArrayCreate(VT_R8, 1, rgsabound); //create the array of 4byte integers, one dimension
double* pData;
 hr = SafeArrayAccessData(  pMySafeArray, (void**)&pData); //Get a pointer to the data.

 for(long count = 0; count < N; count++) (pData[count] = doc->dataz[count]);
 SafeArrayUnaccessData(pMySafeArray);
myVariant.parray = pMySafeArray;
 myVariant.vt = VT_ARRAY|VT_R8;
glf->iir_low(1,&y,myVariant);
bb=(double *)(y.parray->pvData);
//for(int  yy=1;yy<1000;yy++)
//double uu=bb[yy];
doc->maxdata=doc->mindata=bb[0];;
for(long yy=0;yy<doc->total_sec*50;yy++)
{
doc->dataz[yy]=bb[yy];
 if(doc->dataz[yy]>doc->maxdata)
     doc->maxdata=doc->dataz[yy];
if(doc->dataz[yy]<doc->mindata)
     doc->mindata=doc->dataz[yy];
}
 for(count = 0; count < N; count++) (pData[count] = doc->datae[count]);
 SafeArrayUnaccessData(pMySafeArray);
myVariant.parray = pMySafeArray;
 myVariant.vt = VT_ARRAY|VT_R8;
glf->iir_low(1,&y,myVariant);
bb=(double *)(y.parray->pvData);
//for(int  yy=1;yy<1000;yy++)
//double uu=bb[yy];
for(yy=0;yy<doc->total_sec*50;yy++)
{
doc->datae[yy]=bb[yy];
 if(doc->datae[yy]>doc->maxdata)
     doc->maxdata=doc->datae[yy];
if(doc->datae[yy]<doc->mindata)
     doc->mindata=doc->datae[yy];
}


 for(count = 0; count < N; count++) (pData[count] = doc->datan[count]);
 SafeArrayUnaccessData(pMySafeArray);
myVariant.parray = pMySafeArray;
 myVariant.vt = VT_ARRAY|VT_R8;
glf->iir_low(1,&y,myVariant);
bb=(double *)(y.parray->pvData);
//for(int  yy=1;yy<1000;yy++)
//double uu=bb[yy];
for(yy=0;yy<doc->total_sec*50;yy++)
{
doc->datan[yy]=bb[yy];
 if(doc->datan[yy]>doc->maxdata)
     doc->maxdata=doc->datan[yy];
if(doc->datan[yy]<doc->mindata)
     doc->mindata=doc->datan[yy];
}

topdata=(doc->maxdata-doc->mindata);

setdrawdataall();

 

 

Invalidate(true); // TODO: Add your command handler code here
 
}

  评论这张
 
阅读(731)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018