把javascript,vbscript中得数组传递给COM组件(or Activex)

来源:互联网 发布:人类 群婚 知乎 编辑:程序博客网 时间:2024/04/29 16:08
  1. COM组件的方法在IDL中的声明:
  2. [id(1), helpstring("方法InputArray")] HRESULT InputArray([in] VARIANT vData);
  3. 在脚本中建立数组并调用COM组件的方法:
  4. 当数组很大的时候,like 100k ,javascript在给数组赋值的时候效率非常低!完成时间,cpu占用率,占用的内存都大的可怕。反而VBScript却完成的很好。
  5. COM组件的代码:
  6. 从代码中可以看到vbscript传进来的是个SafeArray。而javascript的情况就复杂了,javascript中得数组并不是真正意义上的数组,这个“数组”传到COM中被放进一个集合里,参数VARIANT的类型被置为VT_DISPATCH,我们得通过这个IDispatch指针调用invoke才能得到用来读取集合的枚举接口。
  7. STDMETHODIMP CBigParamCtl::InputArray(VARIANT vData)
  8. {
  9.  LPBYTE p ;
  10.  DWORD nLen;
  11.  HRESULT hr;
  12.  if( vData.vt == VT_DISPATCH)
  13.  { 
  14.   //deal with javascript array
  15.   hr = VariantEnumToBytes(vData.pdispVal,&p,  &nLen);
  16.  }
  17.  else
  18.  {
  19.   //deal with vbscript array
  20.   hr = VariantArrayToBytes(&vData, &p,  &nLen) ;
  21.  }
  22.  if(  S_OK ==  hr)
  23.  {
  24.   //....... do sth on p  
  25.   delete[] p;
  26.  }
  27.  return S_OK;
  28. }
  29. HRESULT VariantEnumToBytes(IDispatch* disp, LPBYTE *ppBytes, DWORD *pdwBytes)
  30. {
  31.  // DebugBreak();
  32.  HRESULT hr;
  33.  DISPPARAMS noArgs = { NULL, NULL, 0, 0 };
  34.  CComVariant resultV;
  35.  hr = disp->Invoke( DISPID_NEWENUM,
  36.   IID_NULL,
  37.   LOCALE_SYSTEM_DEFAULT,
  38.   DISPATCH_PROPERTYGET,
  39.   &noArgs,
  40.   &resultV,
  41.   NULL,
  42.   NULL );
  43.  if( FAILED( hr ) && FAILED( resultV.ChangeType( VT_UNKNOWN ) ) )
  44.   return E_FAIL;
  45.  // Bug 37459, above Invoke succeeds, but returns resultV.vt == VT_EMPTY, resultV->other param unchanged
  46.  if (resultV.vt != VT_UNKNOWN && resultV.vt != VT_DISPATCH)
  47.  {
  48.   return E_FAIL;
  49.  }
  50.  CComQIPtr pEnum( resultV.punkVal );
  51.  if( !pEnum )
  52.   return E_FAIL;
  53.  // Count the elements
  54.  *pdwBytes = 0;
  55.  hr = S_OK;
  56.  //Get Enum Size
  57.  while( hr == S_OK )
  58.  {
  59.   hr = pEnum->Skip(1);
  60.   if( hr == S_OK )
  61.    (*pdwBytes)++;
  62.  }
  63.  //allocate memory
  64.  *ppBytes = (LPBYTE)new BYTE[*pdwBytes];
  65.  int nCount = 0;
  66.  CComVariant elemV;
  67.  pEnum->Reset();
  68.  hr = S_OK;
  69.  while( hr == S_OK )
  70.  {
  71.   // Could switch to use Skip when Cary gets
  72.   // it working.
  73.   hr = pEnum->Next( 1, &elemV, NULL );
  74.   if( elemV.vt != VT_I4 )
  75.    hr = S_FALSE; // correct for dispproxy bug 19307
  76.   else
  77.   {
  78.    int nTmp = elemV.lVal;
  79.    (*ppBytes)[nCount] = (BYTE)nTmp;
  80.   }
  81.   if( hr == S_OK )
  82.    nCount++;
  83.  }
  84.  return S_OK;
  85. }
  86. HRESULT VariantArrayToBytes(VARIANT *pVariant, LPBYTE *ppBytes, DWORD *pdwBytes)
  87. {
  88.  USES_CONVERSION;
  89.  if (pVariant->vt != (VT_VARIANT | VT_BYREF))
  90.   return E_INVALIDARG;
  91.  if (!(pVariant->pvarVal->vt & VT_ARRAY))
  92.   return E_INVALIDARG;
  93.  SAFEARRAY* pX = NULL;
  94.  if (pVariant->pvarVal->vt & VT_BYREF)
  95.   pX = *(pVariant->pvarVal->pparray);
  96.  else
  97.   pX = pVariant->pvarVal->parray;
  98.  if (::SafeArrayGetDim(pX) != 1)
  99.   return E_INVALIDARG;
  100.     *ppBytes = NULL;
  101.     *pdwBytes = 0;
  102.   VARIANT *pArray = NULL;
  103.   HRESULT hr = E_FAIL;
  104.   _variant_t v;
  105.  hr = SafeArrayAccessData(pX, (void **) &pArray );
  106.  if( SUCCEEDED(hr))
  107.  {
  108.   *pdwBytes = pX->rgsabound->cElements;
  109.   *ppBytes = (LPBYTE)new BYTE[*pdwBytes];
  110.   for( DWORD i = 0; i < *pdwBytes; i++)
  111.   {
  112.    v = pArray[i];
  113.    v.ChangeType(VT_UI1);
  114.    (*ppBytes)[i] = v.bVal;
  115.   }
  116.   SafeArrayUnaccessData( pX );
  117.  }
  118.  else
  119.   return hr;
  120.  SafeArrayDestroy(pX);
  121.     return S_OK;
  122. }
 
原创粉丝点击