[id(1), helpstring("方法 InputArray")] HRESULT InputArray([in] VARIANT vData);
SAFEARRAY,VARIANT.vt = VT_ARRAY | VT_VARIANT,效能優異(100k 元素亦流暢)。VARIANT.vt = VT_DISPATCH,需透過 IDispatch::Invoke(DISPID_NEWENUM) 取得列舉器逐一讀取,效能極差(CPU/記憶體佔用極高)。STDMETHODIMP CBigParamCtl::InputArray(VARIANT vData)
{
LPBYTE pData = NULL;
DWORD nLen = 0;
HRESULT hr;
if (vData.vt == VT_DISPATCH) {
// JavaScript 陣列
hr = VariantEnumToBytes(vData.pdispVal, &pData, &nLen);
} else {
// VBScript 陣列
hr = VariantArrayToBytes(&vData, &pData, &nLen);
}
if (SUCCEEDED(hr)) {
// ... 處理 pData ...
delete[] pData;
}
return S_OK;
}
VariantEnumToBytesHRESULT VariantEnumToBytes(IDispatch* disp, LPBYTE* ppBytes, DWORD* pdwBytes)
{
HRESULT hr;
DISPPARAMS noArgs = {0};
CComVariant resultV;
// 取得 _NewEnum 列舉器
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;
if (resultV.vt != VT_UNKNOWN && resultV.vt != VT_DISPATCH) return E_FAIL;
CComQIPtr pEnum(resultV.punkVal);
if (!pEnum) return E_FAIL;
// 計算元素數
*pdwBytes = 0;
while (pEnum->Skip(1) == S_OK) (*pdwBytes)++;
// 配置記憶體
*ppBytes = new BYTE[*pdwBytes];
int nCount = 0;
CComVariant elemV;
pEnum->Reset();
// 逐一讀取並轉換
while (pEnum->Next(1, &elemV, NULL) == S_OK) {
if (elemV.vt != VT_I4) { hr = S_FALSE; break; } // 修正 proxy bug
int nTmp = elemV.lVal;
(*ppBytes)[nCount++] = (BYTE)nTmp;
}
return S_OK;
}
VariantArrayToBytesHRESULT VariantArrayToBytes(VARIANT* pVariant, LPBYTE* ppBytes, DWORD* pdwBytes)
{
if (pVariant->vt != (VT_VARIANT | VT_BYREF)) return E_INVALIDARG;
if (!(pVariant->pvarVal->vt & VT_ARRAY)) return E_INVALIDARG;
SAFEARRAY* pX = (pVariant->pvarVal->vt & VT_BYREF)
? *(pVariant->pvarVal->pparray)
: pVariant->pvarVal->parray;
if (SafeArrayGetDim(pX) != 1) return E_INVALIDARG;
*ppBytes = NULL; *pdwBytes = 0;
VARIANT* pArray = NULL;
HRESULT hr = SafeArrayAccessData(pX, (void**)&pArray);
if (SUCCEEDED(hr)) {
*pdwBytes = pX->rgsabound->cElements;
*ppBytes = new BYTE[*pdwBytes];
_variant_t v;
for (DWORD i = 0; i < *pdwBytes; i++) {
v = pArray[i];
v.ChangeType(VT_UI1);
(*ppBytes)[i] = v.bVal;
}
SafeArrayUnaccessData(pX);
}
SafeArrayDestroy(pX);
return hr;
}
大量資料傳遞(>10k 元素)強烈建議使用 VBScript 或改用二進位 Blob/檔案傳輸,避免 JavaScript 陣列轉換的效能災難。