欢迎访问:常州市武进区嘉泽中心小学网站 !今天是:
栏目列表
您现在的位置是:首页>>教师>>计算机技术>>程序设计>>杂项>>文章内容
把javascript,vbscript中得数组传递给COM组件(or Activex)
发布时间:2008-11-20   点击:   来源:本站原创   录入者:佚名
 

COM组件的方法在IDL中的声明:
[id(1), helpstring("方法InputArray")] HRESULT InputArray([in] VARIANT vData);

在脚本中建立数组并调用COM组件的方法:
当数组很大的时候,like 100k ,javascript在给数组赋值的时候效率非常低!完成时间,cpu占用率,占用的内存都大的可怕。反而VBScript却完成的很好。

COM组件的代码
从代码中可以看到vbscript传进来的是个SafeArray。而javascript的情况就复杂了,javascript中得数组并不是真正意义上的数组,这个“数组”传到COM中被放进一个集合里,参数VARIANT的类型被置为VT_DISPATCH,我们得通过这个IDispatch指针调用invoke才能得到用来读取集合的枚举接口。
STDMETHODIMP CBigParamCtl::InputArray(VARIANT vData)
{
 LPBYTE p ;
 
 DWORD nLen;

 HRESULT hr;

 if( vData.vt == VT_DISPATCH)
 { 
  //deal with javascript array
  hr = VariantEnumToBytes(vData.pdispVal,&p,  &nLen);
 }
 else
 {
  //deal with vbscript array
  hr = VariantArrayToBytes(&vData, &p,  &nLen) ;
 }

 if(  S_OK ==  hr)
 {
  //....... do sth on p  
  delete[] p;
 }
 
 return S_OK;
}

HRESULT VariantEnumToBytes(IDispatch* disp, LPBYTE *ppBytes, DWORD *pdwBytes)
{
 // DebugBreak();
 HRESULT hr;
 DISPPARAMS noArgs = { NULL, NULL, 0, 0 };
 CComVariant resultV;
 hr = disp->Invoke( DISPID_NEWENUM,
  IID_NULL,
  LOCALE_SYSTEM_DEFAULT,
  DISPATCH_PROPERTYGET,
  &noArgs,
  &resultV,
  NULL,
  NULL );
 if( FAILED( hr ) && FAILED( resultV.ChangeType( VT_UNKNOWN ) ) )
  return E_FAIL;
 // Bug 37459, above Invoke succeeds, but returns resultV.vt == VT_EMPTY, resultV->other param unchanged
 if (resultV.vt != VT_UNKNOWN && resultV.vt != VT_DISPATCH)
 {
  return E_FAIL;
 }
 
 CComQIPtr pEnum( resultV.punkVal );
 if( !pEnum )
  return E_FAIL;
 // Count the elements
 *pdwBytes = 0;
 hr = S_OK;
 
 //Get Enum Size
 while( hr == S_OK )
 {
  hr = pEnum->Skip(1);
  if( hr == S_OK )
   (*pdwBytes)++;
 }

 //allocate memory
 *ppBytes = (LPBYTE)new BYTE[*pdwBytes];

 int nCount = 0;
 CComVariant elemV;
 pEnum->Reset();
 hr = S_OK;
 while( hr == S_OK )
 {
  // Could switch to use Skip when Cary gets
  // it working.
  hr = pEnum->Next( 1, &elemV, NULL );
  if( elemV.vt != VT_I4 )
   hr = S_FALSE; // correct for dispproxy bug 19307
  else
  {
   int nTmp = elemV.lVal;
   (*ppBytes)[nCount] = (BYTE)nTmp;
  }
 
  if( hr == S_OK )
   nCount++;
 }
 
 
 return S_OK;
}

HRESULT VariantArrayToBytes(VARIANT *pVariant, LPBYTE *ppBytes, DWORD *pdwBytes)
{
 USES_CONVERSION;
 if (pVariant->vt != (VT_VARIANT | VT_BYREF))
  return E_INVALIDARG;

 if (!(pVariant->pvarVal->vt & VT_ARRAY))
  return E_INVALIDARG;


 SAFEARRAY* pX = NULL;
 

 if (pVariant->pvarVal->vt & VT_BYREF)
  pX = *(pVariant->pvarVal->pparray);
 else
  pX = pVariant->pvarVal->parray;

 if (::SafeArrayGetDim(pX) != 1)
  return E_INVALIDARG;


    *ppBytes = NULL;
    *pdwBytes = 0;

  VARIANT *pArray = NULL;
  HRESULT hr = E_FAIL;

  _variant_t v;
 hr = SafeArrayAccessData(pX, (void **) &pArray );
 if( SUCCEEDED(hr))
 {
  *pdwBytes = pX->rgsabound->cElements;
  *ppBytes = (LPBYTE)new BYTE[*pdwBytes];

  for( DWORD i = 0; i < *pdwBytes; i++)
  {
   v = pArray[i];
   v.ChangeType(VT_UI1);
   (*ppBytes)[i] = v.bVal;
  }

  SafeArrayUnaccessData( pX );
 }
 else
  return hr;

 SafeArrayDestroy(pX);

    return S_OK;
}


附件:
    关闭窗口
    打印文档
    账号登录
    保持登录 忘记密码?
    账号与武进教师培训平台同步