- 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;
- }