Requirement:
1.创建myCom.dll,该COM只有一个组件,两个接口IGetRes--方法Hello(),IGetResEx--方法HelloEx();
2.在工程中导入组件或类型库
#import
"
组件所在目录myCom.dll
"
no_namespace 或
#import
"
类型库所在目录myCom.tlb
"
using
namespace
MYCOM;
方式1
CoInitialize(NULL);
CLSID clsid;
CLSIDFromProgID(OLESTR(
"
myCom.GetRes
"
),
//
&
clsid);
//
CComPtr
<
IGetRes
>
pGetRes;
//
智能指针
pGetRes.CoCreateInstance(clsid);
pGetRes
->
Hello();
pGetRes.Release();
//
小心哦,请看最后的“注意”
CoUninitialize();
方式2
CoInitialize(NULL);
CLSID clsid;
HRESULT hr
=
CLSIDFromProgID(OLESTR(
"
myCom.GetRes
"
),
&
clsid);
IGetRes
*
ptr
=
NULL;
hr
=
CoCreateInstance(clsid,
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IGetRes),
(LPVOID
*
)
&
ptr);
ptr
->
Hello();
CoUninitialize();
方式3
CoInitialize(NULL);
HRESULT hr;
CLSID clsid;
hr
=
CLSIDFromProgID(OLESTR(
"
myCom.GetRes
"
),
&
clsid);
IGetRes
*
ptr
=
NULL;
IGetResEx
*
ptrEx
=
NULL;
//
使用CoCreateClassObject创建一个组件(特别是mutilThreads)的多个对象的时候,效率更高.
IClassFactory
*
p_classfactory
=
NULL;
hr
=
CoGetClassObject(clsid,
CLSCTX_INPROC_SERVER,
NULL,
IID_IClassFactory,
(LPVOID
*
)
&
p_classfactory);
p_classfactory
->
CreateInstance(NULL,
__uuidof(IGetRes),
(LPVOID
*
)
&
ptr);
p_classfactory
->
CreateInstance(NULL,
__uuidof(IGetResEx),
(LPVOID
*
)
&
ptrEx);
ptr
->
Hello();
ptrEx
->
HelloEx();
CoUninitialize();
直接从dll中得到DllGetClassObject,接着生成类对象及类实例(这方法可以使组件不用在注册表里注册,这是最原始的方法,但这样做没什么意义,至少失去了COM对用户的透明性),不推荐使用。
方式4
//
定义一个函数指针类型
typedef HRESULT (__stdcall
*
pfnHello)(REFCLSID,REFIID,
void
**
);
pfnHello fnHello
=
NULL;
//
创建一个函数指针变量
//
将COM组件DLL像一般DLL一样加载,得到DLL句柄
HINSTANCE hdllInst
=
LoadLibrary(
"
*:\*.dll
"
);
//
判断DLL加载是否成功
if
(NULL
!=
hdllInst)
{
//
取得相应的函数地址
fnHello
=
(pfnHello)GetProcAddress(hdllInst,
"
DllGetClassObject
"
);
if
(NULL
!=
fnHello)
{
//
得到类工厂接口指针
IClassFactory
*
pcf
=
NULL;
HRESULT hr
=
(fnHello)(CLSID_GetRes,
IID_IClassFactory,
(
void
**
)
&
pcf);
if
(SUCCEEDED(hr)
&&
(pcf
!=
NULL))
{
//
得到具体方法接口指针
IGetRes
*
pGetRes
=
NULL;
hr
=
pcf
->
CreateInstance(NULL,
IID_IFoo,
(
void
**
)
&
pGetRes);
if
(SUCCEEDED(hr)
&&
(pGetRes
!=
NULL))
{
pGetRes
->
Hello();
pGetRes
->
Release();
}
pcf
->
Release();
}
}
FreeLibrary(hdllInst);
}
------------------------------------方式5 ------------------------------------
通过ClassWizard利用类型库生成包装类,不过前提是com组件的接口必须是派生自IDispatch,具体方法:
调出添加类向导(.NET中),选择类型库中MFC类,打开,选择"文件",选择"myCom.dll"或"myCom.tlb",接下来会出来该myCom中的所有接口,选择你想生成的接口包装类后,向导会自动生成相应的.h文件.这样你就可以在你的MFC中像使用普通类那样使用组件了.(CreateDispatch("myCom.GetRes") 中的参数就是ProgID通过Clsid在注册表中可以查询的到)
CoInitialize(NULL);
CGetRes getRest;
if
(getRest.CreateDispatch(
"
myCom.GetRes
"
)
!=
0
)
{
getRest.Hello();
getRest.ReleaseDispatch();
}
CoUninitialize();
------------------------------------ 注意------------------------------------
COM中的智能指针实际上是重载了->的类,目的是为了简化引用记数,不需要程序员显示的调用AddRef()和Release(),但是为什么我们在Method 1中pGetRes.Release(),问题在于,我们的智能指针pGetRes生命周期的结束是在CoUninitialize()之后,CoInitialize所开的套间在CoUninitialize()后已经被关闭,而pGetRes此时发生析构,导致了程序的崩溃,解决这个问题的另一个方法是:
代码
CoInitialize(NULL);
CLSID clsid;
CLSIDFromProgID(OLESTR(
"
myCom.GetRes
"
),
&
clsid);
CComPtr
<
IGetRes
>
pGetRes;
//
智能指针
pGetRes.CoCreateInstance(clsid);
pGetRes
->
Hello();
//
pGetRes.Release();
//
将其注释掉
CoUninitialize();
--------------------------------------------------------------------
以上就是COM的5中方法,当然具体怎么使用还是要根据具体情况而定。
转载于:https://www.cnblogs.com/rogee/archive/2010/10/03/1841680.html
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)