设为首页 加入收藏

TOP

12.1.6 使用C++API创建COM对象
2013-10-07 00:16:21 来源: 作者: 【 】 浏览:72
Tags:12.1.6 使用 API 创建 COM 对象

12.1.6  使用C++(www.cppentry.com)API创建COM对象

1.问题阐述

COM的设计目的,是要能实现跨语言的调用,既然是跨语言的,那么组件的接口描述就必须在任何语言环境中都要能够认识。如何实现模块之间的调用呢?

2.实现技巧

微软使用了一个新的文件格式IDL文件(接口定义描述语言)。IDL是一个文本文件,IDL经过编译,生成二进制的等价类型库文件 TLB 提供给其他语言来使用。

调用组件程序的方法可以有#include 头文件的方法和#import 类库方法。COM对象的创建由API函数CoCreateInstance完成,其函数原型声明如下:

STDAPI CoCreateInstance(
REFCLSID rclsid,    
LPUNKNOWN pUnkOuter,
DWORD dwClsContext, 
REFIID riid,        
LPVOID * ppv      
);

第一个参数是组件的CLSID,第二个参数聚合时才能用到,第三个参数为进程内的服务,第四个参数为接口的IID,第五个参数返回接口的指针。
3.实例代码

本实例演示了如何调用COM组件。首先生成一个COM组件,然后再生成一个主程序调用COM组件。

在上面的建立的COM组件中增加两个函数,其中一个完成一个简单的加法运算,另一个完成一个字符串的连接任务,代码如下。

完成加法任务的函数代码:

 STDMETHODIMP CFun::Add(long a, long b, long *retval)
{
// TODO: 在此添加相关代码
*retval = a+b;
return S_OK;
}
完成字符串连接的代码:
STDMETHODIMP CFun::CatString(BSTR str1, BSTR str2, BSTR *pretval)
{
// TODO: 在此添加相关代码
int nLen1 = ::SysStringLen(str1);   //计算BSTR字符串的长度
int nLen2 = ::SysStringLen(str2);
*pretval = ::SysAllocStringLen(str1,nLen1+nLen2);
//申请nLen1+nLen2长度的内存区域,将字符串存进去
if(nLen2>0)
{
::memcpy(pretval+nLen1,str2,sizeof(WCHAR)*nLen2);
//将str2复制进申请的内存缓冲区
}
return S_OK;
}
调用组件的代码,首先将组件ID、接口ID及接口的函数集包含在工程中,代码如下:
 #include "..\Object\OBJECT.h"
#include "..\Object\OBJECT_i.c"
调用过程如下所示:
/*将BSTR转换为CString*/
CString convert(BSTR b)
{
CString s;
if(b == NULL)
return s; // empty for NULL BSTR
#ifdef UNICODE
s = b;
#else
LPSTR p = s.GetBuffer(SysStringLen(b) + 1);
::WideCharToMultiByte(CP_ACP,           
0,                
b,                
-1,               
p,                
SysStringLen(b)+1,
NULL,             
NULL);            
s.ReleaseBuffer();
#endif
return s;
}
void CExample1Dlg::OnExeBtn()
{
// TODO: 在此添加相关代码
::CoInitialize( NULL );
UpdateData(TRUE);
IFun* pFun = NULL;
IUnknown* pUn = NULL;
try
{
HRESULT hr = ::CoCreateInstance(
CLSID_Fun,
NULL,
CLSCTX_INPROC_SERVER,
IID_IUnknown,
(LPVOID*)&pUn
);
if(FAILED(hr))
{
MessageBox("请您注册组件");
return;
}
hr = pUn->QueryInterface(IID_IFun,(LPVOID*)&pFun);
if(FAILED(hr))
{
MessageBox("检查接口是否存在");
return;
}
pFun->Add(m_add1,m_add2,&m_add3);
BSTR  bstr1 = m_strCat1.AllocSysString();
BSTR  bstr2 = m_strCat2.AllocSysString();
BSTR  bstr3;
pFun->CatString(bstr1,bstr2,&bstr3);
m_strCat3 = convert(bstr3);
UpdateData(FALSE);

}
catch ( LPCTSTR lpErr)
{
AfxMessageBox(lpErr);
}
pUn->Release();  //释放接口
pFun->Release();  //释放接口
::CoUninitialize();
}
使用API创建接口实例,最后不要忘记了加接口指针Realease。大部分COM的API都是以Co开头的,这个前缀是COM Object的缩写。
【责任编辑:夏书 TEL:(010)68476606】

回书目   上一节   下一节

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇12.1.8 使用智能指针的封装类创建.. 下一篇12.2.1 VC++实现Office自动化

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: