COM初探(五)——从IDispatch接口继承
(一)目标
本文用一个简单的例子来讲述如何使我们的COM对象可以被脚本语言调用。
(二)IDL文件
为了在脚本语言环境中使用COM组件,COM规范规定要在脚本语言环境使用的COM必须实现IDispatch接口。
下面我们定义接口ITimeBeijing,请注意这个文件和我们以前的文件的不同点:
import "oaidl.idl";
import "ocidl.idl";
[
uuid(30002489-29D8-4c48-9B1F-D6660A818E7B),
object,
dual,//这个标识说明定义的是双接口
pointer_default(unique)
]
interface ITimeBeijing : IDispatch//必须从IDispatch接口派生
{
[id(1)] HRESULT GetHour([out, retval] int * hour);//每个函数前都有id号,便于调用
[id(2)] HRESULT GetMinute([out, retval] int * min);
[id(3)] HRESULT GetSecond([out, retval] int * sec);
};
[
uuid(8AE3C9BA-CEE9-4d33-A4C1-DB4FBFBB9A43),
version(1.0),
]
library TimeBeijingLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
[
uuid(ECE8BF15-11FB-45a4-90A1-1788DDAB31AC),
]
coclass TimeBeijingClass//com类
{
[default] interface ITimeBeijing;
};
};
(三)建立COM类TimeBeijingClass
请注意和以前的不同点。
这里的类需要实现3个接口:IUnknown, IDispatch和ITimeBeijing。
// TimeBeijingClass.h: interface for the TimeBeijingClass class.
//
//
#if !defined(AFX_TIMEBEIJINGCLASS_H__E9800212_16E2_4BE3_B646_420DC02F50AE__INCLUDED_)
#define AFX_TIMEBEIJINGCLASS_H__E9800212_16E2_4BE3_B646_420DC02F50AE__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "TimeBeijing.h"
class TimeBeijingClass : public ITimeBeijing
{
public:
TimeBeijingClass();
~TimeBeijingClass();
public:
// IUnknown
STDMETHOD(QueryInterface)(REFIID riid, void **ppv);
STDMETHOD_(ULONG, AddRef)();
STDMETHOD_(ULONG, Release)();
// IDispatch
STDMETHOD(GetTypeInfoCount)(UINT * pit);
STDMETHOD(GetTypeInfo)(UINT it,LCID lcid,ITypeInfo **ppti);
STDMETHOD(GetIDsOfNames)(REFIID riid,
OLECHAR ** pNames,
UINT nNames,
LCID lcid,
DISPID * pdispids);
STDMETHOD(Invoke)(DISPID id,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS *pd,
VARIANT * pVarResult,
EXCEPINFO * pe,
UINT *pu);
// ITimeBeijing
STDMETHOD(GetHour)(int * hour);
STDMETHOD(GetMinute)(int * min);
STDMETHOD(GetSecond)(int * sec);
private:
LONG m_cRef;
};
#endif // !defined(AFX_TIMEBEIJINGCLASS_H__E9800212_16E2_4BE3_B646_420DC02F50AE__INCLUDED_)
// TimeBeijingClass.cpp: implementation of the TimeBeijingClass class.
//
//
#include "TimeBeijingClass.h"
#include "stdio.h"
#include <time.h>
#include "TimeBeijing_i.c"
//
// Construction/Destruction
//
TimeBeijingClass::TimeBeijingClass()
{
printf("TimeBeijingClass - Constructor/n");
m_cRef = 0;
}
TimeBeijingClass::~TimeBeijingClass()
{
printf("TimeBeijingClass - Destructor/n");
}
// IUnknown
STDMETHODIMP TimeBeijingClass::QueryInterface(REFIID riid, void **ppv)
{
printf("TimeBeijingClass - QueryInterface/n");
if(riid == IID_ITimeBeijing)
*ppv = static_cast<ITimeBeijing *>(this);
else if(riid == IID_IUnknown)
*ppv = static_cast<ITimeBeijing *>(this);
else if(riid == IID_IDispatch)
*ppv = static_cast<IDispatch *>(this);
else {
*ppv = 0;
return E_NOINTERFACE