用於指令碼的IDispatch實現

來源:互聯網
上載者:User

做這個Dispatch實現基類的目標有3個:

1。能夠很方便滴映射成員供指令碼(包括使用WebBrowser的external對象) 訪問;

2。最好能不依賴MFC;

3。不用tlb檔案,不寫註冊表。

實現的時候,參考了Delphi的ComAutoObj(話說回來,這個單元的BUG可不小,上次做的時候用著用著就出錯。。。還好有個好心的澳大利亞青年發了個補丁……扯到哪裡去了-___-b) 最後完成下來,衍生類別中的映射是這樣滴,看起來還不錯:P,也沒有像MFC的CDispatchHelper裡面的VTS_I4這樣的東東了:

 BEGIN_AC_DISPMAP(CMyGlobal)
  AC_DISP_FUNCTION(1, L"alert", alert)
  AC_DISP_FUNCTION(2, L"add", add2)
  AC_DISP_PROP(3, L"count", get_count, put_count)
  AC_DISP_READONLYPROP(4, L"beeper", get_beeper)
 END_AC_DISPMAP()

不多說鳥,貼CODE:

ACDispatch.h

#pragma once

#include "oaidl.h"
#include "comutil.h"

#define BEGIN_AC_DISPMAP(theClass) /
 typedef void (theClass::*_AC_DispP1Func)(_variant_t, _variant_t&);/
 HRESULT MultiParamInvoke(_AC_DispP1Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
 {/
  if ( pDispParams->cArgs != 1 ) return E_INVALIDARG;/
  _variant_t v1(pDispParams->rgvarg[0]);/
  _variant_t retval;/
  (this->*func)(v1, retval);/
  if (pVarResult) *pVarResult = retval;/
  return S_OK;/
 }/
 typedef void (theClass::*_AC_DispP2Func)(_variant_t, _variant_t, _variant_t&);/
 HRESULT MultiParamInvoke(_AC_DispP2Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
 {/
 if ( pDispParams->cArgs != 2 ) return E_INVALIDARG;/
 _variant_t v1(pDispParams->rgvarg[0]);/
 _variant_t v2(pDispParams->rgvarg[1]);/
 _variant_t retval;/
 (this->*func)(v1, v2, retval);/
 if (pVarResult) *pVarResult = retval;/
 return S_OK;/
 }/
 typedef void (theClass::*_AC_DispP3Func)(_variant_t, _variant_t, _variant_t, _variant_t&);/
 HRESULT MultiParamInvoke(_AC_DispP3Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
 {/
 if ( pDispParams->cArgs != 3 ) return E_INVALIDARG;/
 _variant_t v1(pDispParams->rgvarg[0]);/
 _variant_t v2(pDispParams->rgvarg[1]);/
 _variant_t v3(pDispParams->rgvarg[2]);/
 _variant_t retval;/
 (this->*func)(v1, v2, v3, retval);/
 if (pVarResult) *pVarResult = retval;/
 return S_OK;/
 }/
 typedef void (theClass::*_AC_DispP4Func)(_variant_t, _variant_t, _variant_t, _variant_t, _variant_t&);/
 HRESULT MultiParamInvoke(_AC_DispP4Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
 {/
 if ( pDispParams->cArgs != 4 ) return E_INVALIDARG;/
 _variant_t v1(pDispParams->rgvarg[0]);/
 _variant_t v2(pDispParams->rgvarg[1]);/
 _variant_t v3(pDispParams->rgvarg[2]);/
 _variant_t v4(pDispParams->rgvarg[3]);/
 _variant_t retval;/
 (this->*func)(v1, v2, v3, v4, retval);/
 if (pVarResult) *pVarResult = retval;/
 return S_OK;/
 }/
 typedef void (theClass::*_AC_DispP5Func)(_variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t&);/
 HRESULT MultiParamInvoke(_AC_DispP5Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
 {/
 if ( pDispParams->cArgs != 5 ) return E_INVALIDARG;/
 _variant_t v1(pDispParams->rgvarg[0]);/
 _variant_t v2(pDispParams->rgvarg[1]);/
 _variant_t v3(pDispParams->rgvarg[2]);/
 _variant_t v4(pDispParams->rgvarg[3]);/
 _variant_t v5(pDispParams->rgvarg[4]);/
 _variant_t retval;/
 (this->*func)(v1, v2, v3, v4, v5, retval);/
 if (pVarResult) *pVarResult = retval;/
 return S_OK;/
 }/
 typedef void (theClass::*_AC_DispP6Func)(_variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t&);/
 HRESULT MultiParamInvoke(_AC_DispP6Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
 {/
 if ( pDispParams->cArgs != 6 ) return E_INVALIDARG;/
 _variant_t v1(pDispParams->rgvarg[0]);/
 _variant_t v2(pDispParams->rgvarg[1]);/
 _variant_t v3(pDispParams->rgvarg[2]);/
 _variant_t v4(pDispParams->rgvarg[3]);/
 _variant_t v5(pDispParams->rgvarg[4]);/
 _variant_t v6(pDispParams->rgvarg[5]);/
 _variant_t retval;/
 (this->*func)(v1, v2, v3, v4, v5, v6, retval);/
 if (pVarResult) *pVarResult = retval;/
 return S_OK;/
 }/
 typedef void (theClass::*_AC_DispP7Func)(_variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t&);/
 HRESULT MultiParamInvoke(_AC_DispP7Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
 {/
 if ( pDispParams->cArgs != 7 ) return E_INVALIDARG;/
 _variant_t v1(pDispParams->rgvarg[0]);/
 _variant_t v2(pDispParams->rgvarg[1]);/
 _variant_t v3(pDispParams->rgvarg[2]);/
 _variant_t v4(pDispParams->rgvarg[3]);/
 _variant_t v5(pDispParams->rgvarg[4]);/
 _variant_t v6(pDispParams->rgvarg[5]);/
 _variant_t v7(pDispParams->rgvarg[6]);/
 _variant_t retval;/
 (this->*func)(v1, v2, v3, v4, v5, v6, v7, retval);/
 if (pVarResult) *pVarResult = retval;/
 return S_OK;/
 }/
 typedef void (theClass::*_AC_DispP8Func)(_variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t&);/
 HRESULT MultiParamInvoke(_AC_DispP8Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
 {/
 if ( pDispParams->cArgs != 8 ) return E_INVALIDARG;/
 _variant_t v1(pDispParams->rgvarg[0]);/
 _variant_t v2(pDispParams->rgvarg[1]);/
 _variant_t v3(pDispParams->rgvarg[2]);/
 _variant_t v4(pDispParams->rgvarg[3]);/
 _variant_t v5(pDispParams->rgvarg[4]);/
 _variant_t v6(pDispParams->rgvarg[5]);/
 _variant_t v7(pDispParams->rgvarg[6]);/
 _variant_t v8(pDispParams->rgvarg[7]);/
 _variant_t retval;/
 (this->*func)(v1, v2, v3, v4, v5, v6, v7, v8, retval);/
 if (pVarResult) *pVarResult = retval;/
 return S_OK;/
 }/
 typedef void (theClass::*_AC_DispP9Func)(_variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t&);/
 HRESULT MultiParamInvoke(_AC_DispP9Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
 {/
 if ( pDispParams->cArgs != 9 ) return E_INVALIDARG;/
 _variant_t v1(pDispParams->rgvarg[0]);/
 _variant_t v2(pDispParams->rgvarg[1]);/
 _variant_t v3(pDispParams->rgvarg[2]);/
 _variant_t v4(pDispParams->rgvarg[3]);/
 _variant_t v5(pDispParams->rgvarg[4]);/
 _variant_t v6(pDispParams->rgvarg[5]);/
 _variant_t v7(pDispParams->rgvarg[6]);/
 _variant_t v8(pDispParams->rgvarg[7]);/
 _variant_t v9(pDispParams->rgvarg[8]);/
 _variant_t retval;/
 (this->*func)(v1, v2, v3, v4, v5, v6, v7, v8, v9, retval);/
 if (pVarResult) *pVarResult = retval;/
 return S_OK;/
 }/
 typedef void (theClass::*_AC_DispP10Func)(_variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t&);/
 HRESULT MultiParamInvoke(_AC_DispP10Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
 {/
 if ( pDispParams->cArgs != 10 ) return E_INVALIDARG;/
 _variant_t v1(pDispParams->rgvarg[0]);/
 _variant_t v2(pDispParams->rgvarg[1]);/
 _variant_t v3(pDispParams->rgvarg[2]);/
 _variant_t v4(pDispParams->rgvarg[3]);/
 _variant_t v5(pDispParams->rgvarg[4]);/
 _variant_t v6(pDispParams->rgvarg[5]);/
 _variant_t v7(pDispParams->rgvarg[6]);/
 _variant_t v8(pDispParams->rgvarg[7]);/
 _variant_t v9(pDispParams->rgvarg[8]);/
 _variant_t v10(pDispParams->rgvarg[9]);/
 _variant_t retval;/
 (this->*func)(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, retval);/
 if (pVarResult) *pVarResult = retval;/
 return S_OK;/
 }/
 virtual HRESULT GetIDOrInvoke(BOOL bGetID, WORD wFlags, LPOLESTR szName, DISPPARAMS *pDispParams, VARIANT *pVarResult, DISPID* rgDispID)/
 {/

#define END_AC_DISPMAP() /
  return E_NOTIMPL;/
 }

#define AC_DISP_FUNCTION(id, funcName, funcptr) /
  if ( bGetID && wcscmp(szName, funcName) == 0 )/
  {/
   *rgDispID = id;/
   return S_OK; /
  }/
  else if ( (!bGetID) && *rgDispID == id ) /
  { /
   return MultiParamInvoke(funcptr, pDispParams, pVarResult);/
  }

#define AC_DISP_PROP(id, propName, getfunc, putfunc) /
 if ( bGetID && wcscmp(szName, propName) == 0 )/
 {/
  *rgDispID = id;/
  return S_OK;/
 }/
 else if ( (!bGetID) && *rgDispID == id ) /
 { /
  if ( wFlags & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) ) /
  { /
   if ( pDispParams->cNamedArgs != 1 || pDispParams->rgdispidNamedArgs[0] != DISPID_PROPERTYPUT ) return DISP_E_MEMBERNOTFOUND; /
   putfunc(_variant_t(pDispParams->rgvarg[0]));/
   return S_OK; /
  } /
  else /
  { /
   if ( pDispParams->cArgs != 0 ) return DISP_E_BADPARAMCOUNT; /
   _variant_t retval; /
   getfunc(retval); /
   *pVarResult = retval; /
   return S_OK; /
  } /
 }

#define AC_DISP_READONLYPROP(id, propName, getfunc) /
 if ( bGetID && wcscmp(szName, propName) == 0 )/
 {/
  *rgDispID = id;/
  return S_OK;/
 }/
 else if ( (!bGetID) && *rgDispID == id ) /
 { /
  if ( pDispParams->cArgs != 0 ) return DISP_E_BADPARAMCOUNT; /
  _variant_t retval; /
  getfunc(retval); /
  *pVarResult = retval; /
  return S_OK; /
 } /

/********************** 廣告位招租 *************************/

/*
 * CACAutoDispatch : a simple dispatch driver used for script
 */
class CACAutoDispatch : public IDispatch
{
private:
 UINT m_uRefCount;
public:
 CACAutoDispatch(BOOL bZeroRefCount);
 virtual ~CACAutoDispatch(void);
public:
 virtual HRESULT STDMETHODCALLTYPE QueryInterface(
  /* [in] */ REFIID riid,
  /* [iid_is][out] */ void ** ppvObject);

 virtual ULONG STDMETHODCALLTYPE AddRef(void);

 virtual ULONG STDMETHODCALLTYPE Release(void);

 virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(
  /* [out] */ UINT *pctinfo);

 virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(
  /* [in] */ UINT iTInfo,
  /* [in] */ LCID lcid,
  /* [out] */ ITypeInfo **ppTInfo);

 virtual HRESULT GetIDOrInvoke(BOOL bGetID, WORD wFlags, LPOLESTR szName, DISPPARAMS *pDispParams, VARIANT *pVarResult, DISPID* rgDispID) = 0;

 virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(
  /* [in] */ REFIID riid,
  /* [size_is][in] */ LPOLESTR *rgszNames,
  /* [in] */ UINT cNames,
  /* [in] */ LCID lcid,
  /* [size_is][out] */ DISPID *rgDispId)
 {
  return GetIDOrInvoke(TRUE, 0, rgszNames[0], NULL, NULL, rgDispId);
 }

 virtual /* [local] */ HRESULT STDMETHODCALLTYPE Invoke(
  /* [in] */ DISPID dispIdMember,
  /* [in] */ REFIID riid,
  /* [in] */ LCID lcid,
  /* [in] */ WORD wFlags,
  /* [out][in] */ DISPPARAMS *pDispParams,
  /* [out] */ VARIANT *pVarResult,
  /* [out] */ EXCEPINFO *pExcepInfo,
  /* [out] */ UINT *puArgErr)
 {
  return GetIDOrInvoke(FALSE, wFlags, NULL, pDispParams, pVarResult, &dispIdMember);
 }
};

ACDispatch.cpp

#include "StdAfx.h"
#include "./acdispatch.h"

/* Note: we initialized the ref count to zero to make the object
 auto-deleted by script engine when bZeroRefCount is TRUE,
   *NEVER* call Release() in constructor */
CACAutoDispatch::CACAutoDispatch(BOOL bZeroRefCount) : m_uRefCount(1)
{
 if (bZeroRefCount) m_uRefCount = 0;
}

CACAutoDispatch::~CACAutoDispatch(void)
{
}

HRESULT STDMETHODCALLTYPE CACAutoDispatch::QueryInterface(
 /* [in] */ REFIID riid,
 /* [iid_is][out] */ void **ppvObject)
{
 if ( riid == IID_IUnknown || riid == IID_IDispatch )
 {
  this->AddRef();
  *ppvObject = this;
  return S_OK;
 }
 else
 {
  *ppvObject = NULL;
  return E_NOINTERFACE;
 }
}

ULONG STDMETHODCALLTYPE CACAutoDispatch::AddRef(void)
{
 return ++m_uRefCount;
}

ULONG STDMETHODCALLTYPE CACAutoDispatch::Release(void)
{
 ULONG ret = --m_uRefCount;
 if (ret == 0) delete this;
 return ret;
}

STDMETHODIMP CACAutoDispatch::GetTypeInfoCount(
 /* [out] */ UINT *pctinfo)
{
 return E_NOTIMPL;
}

STDMETHODIMP CACAutoDispatch::GetTypeInfo(
 /* [in] */ UINT iTInfo,
 /* [in] */ LCID lcid,
 /* [out] */ ITypeInfo **ppTInfo)
{
 return E_NOTIMPL;
}

下面是用一個console工程測試的代碼,測試的指令碼環境當然是msscriptcontrol,真是方便亞。

// testcons2.cpp : 定義控制台應用程式的進入點。
//

#include "stdafx.h"
#include "conio.h"
#include "atlstr.h"
#include "d:/design/ac/acdispatch.h"
#include "comutil.h"

#import "c:/windows/system32/msscript.ocx"

class CBeeper2 : public CACAutoDispatch
{
private:
 void beep(_variant_t msg, _variant_t& retval)
 {
  CString str = msg;
  printf("beep:%s/n", str);
 }
public:
 CBeeper2(BOOL bZeroRefCount) : CACAutoDispatch(bZeroRefCount)
 {
 }
 ~CBeeper2()
 {
 }
public:
 BEGIN_AC_DISPMAP(CBeeper2)
  AC_DISP_FUNCTION(1, L"beep", beep)
 END_AC_DISPMAP()
};

class CMyGlobal : public CACAutoDispatch
{
private:
 void alert(_variant_t msg, _variant_t& retval)
 {
  CString str = msg;
  printf("%s/n", str);
 }
 void add2(_variant_t v1, _variant_t v2, _variant_t& retval)
 {
  int p1 = v1;
  int p2 = v2;
  retval = p1 + p2;
 }
 int m_count;
 void put_count(_variant_t v1)
 {
  m_count = v1;
 }

 void get_count(_variant_t& retval)
 {
  retval = m_count;
 }

 void get_beeper(_variant_t& retval)
 {
  // init ref count to 1
  retval = new CBeeper2(FALSE);
 }
public:
 CMyGlobal(BOOL bZeroRefCount) : CACAutoDispatch(bZeroRefCount)
 {
  m_count = 0;
 }
 ~CMyGlobal()
 {
 }
public:
 BEGIN_AC_DISPMAP(CMyGlobal)
  AC_DISP_FUNCTION(1, L"alert", alert)
  AC_DISP_FUNCTION(2, L"add", add2)
  AC_DISP_PROP(3, L"count", get_count, put_count)
  AC_DISP_READONLYPROP(4, L"beeper", get_beeper)
 END_AC_DISPMAP()
};

using namespace MSScriptControl;

int _tmain(int argc, _TCHAR* argv[])
{
 ::CoInitialize(NULL);
 {
  IScriptControlPtr pCtrl;
  pCtrl.CreateInstance(__uuidof(ScriptControl));
  pCtrl->put_Language(_bstr_t("javascript"));
  pCtrl->AddObject( _bstr_t("myglobal"), new CMyGlobal(TRUE), VARIANT_TRUE );
  /* 以下這句將列印出beep:3 */
  pCtrl->ExecuteStatement("count = 2; beeper.beep(add('1', count));");
  pCtrl = NULL;
 }
 ::CoUninitialize();
 getch();
 return 0;
}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.