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