ATL或COM如何处理JS传递的数组

最近碰到方正客户提出的一个问题,就是对于js定义的数组传递给我们的接口(ATL控件),值设置不进去,一直返回false。

经过查找原因,发现控件代码只处理了vb脚本类的数组,而js数组要特殊处理vbscript传进来的是个SafeArray。而javascript的情况就复杂了,javascript中得数组并不是真正意义上的数组,这个“数组”传到COM中被放进一个集合里,参数VARIANT的类型被置为VT_DISPATCH,我们得通过这个IDispatch指针调用invoke 才能得到用来读取集合的枚举接口。也就是说JS中的Array在COM中是一个实现了IDispatch的对象,可通过IDispatch接口api进行操作。

知道原因后就对接口实现做出如下调整:

首先定义两个辅助函数分别用来获取js数组的长度及指定index元素值

/***********************************************

书写人 :zhichao.wang

函数类型:辅助函数

函数名称:lcl_GetJSArrayLength

函数功能:获取Javascript数组中长度

返回值 :

***********************************************/

HRESULTCNsoControl::lcl_GetJSArrayLength(IDispatch* pDisp, int&pLength)

{

BSTR varName = L"length";

VARIANT varValue;

DISPPARAMS noArgs = {NULL, NULL, 0, 0};

DISPID dispId;

HRESULT hr;

hr = pDisp->GetIDsOfNames(IID_NULL,&varName, 1, LOCALE_USER_DEFAULT, &dispId);

if(FAILED(hr))

returnhr;

hr = pDisp->Invoke(dispId, IID_NULL,LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &noArgs, &varValue, NULL,NULL);

if(SUCCEEDED(hr))

{

pLength = varValue.intVal;

returnhr;

}

else

{

returnhr;

}

}

/***********************************************

书写人 :zhichao.wang

函数类型:辅助函数

函数名称:lcl_GetJSArrayLength

函数功能:获取Javascript数组中指定位置的元素值

返回值 :

***********************************************/

HRESULTCNsoControl::lcl_GetJSArrayDataOfIndex(IDispatch* pDisp, int index, VARIANT& pValue)

{

CComVariant varName(index, VT_I4); // 数组下标

DISPPARAMS noArgs = {NULL, NULL, 0, 0};

DISPID dispId;

VARIANT varValue;

HRESULT hr = 0;

varName.ChangeType(VT_BSTR); // 将数组下标转为数字型,以进行GetIDsOfNames

//

// 获取通过下标访问数组的过程,将过程名保存在dispId中

//

hr = pDisp->GetIDsOfNames(IID_NULL,&varName.bstrVal, 1, LOCALE_USER_DEFAULT, &dispId);

if(FAILED(hr))

return hr;

//

// 调用COM过程,访问指定下标数组元素,根据dispId 将元素值保存在varValue中

//

hr = pDisp->Invoke(dispId, IID_NULL,LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET,&noArgs, &varValue, NULL,NULL);

if(SUCCEEDED(hr))

{

pValue = varValue;

return hr;

}

else

{

return hr;

}

}

然后在对应的接口中做如下处理:

STDMETHODIMPCNsoControl::SetCompoundBoxCodeAndValueByArray(BSTR sName,VARIANTlstCode,VARIANT lstValue,int iType,VARIANT_BOOL*pVal)

{

*pVal = VARIANT_FALSE;

HRESULT hr;

**************此处省略若干业务相关代码************************

if( lstCode.vt == VT_DISPATCH &&lstValue.vt == VT_DISPATCH )//处理JS数组

{

//MessageBox(L"BeginToSetNo1");

intiCodeLen,iValueLen;

lcl_GetJSArrayLength(lstCode.pdispVal,iCodeLen);

lcl_GetJSArrayLength(lstValue.pdispVal,iValueLen);

VARIANT vCode,vValue;

for(int i=0;i<iCodeLen;i++ )

{

lcl_GetJSArrayDataOfIndex(lstCode.pdispVal,i,vCode);

lcl_GetJSArrayDataOfIndex(lstValue.pdispVal,i,vValue);

vParam[1] =CComVariant(vCode.bstrVal);

vParam[0] =CComVariant(vValue.bstrVal);

**************此处省略若干业务相关代码************************

}

*pVal = VARIANT_TRUE;

}

else//处理VB数组等

{

if((lstCode.vt^VT_ARRAY) <1 || (lstCode.vt^VT_ARRAY)>73)//用户传入数组类型不正确直接返回

return S_OK;

if((lstValue.vt^VT_ARRAY) <1 || (lstValue.vt^VT_ARRAY)>73)//用户传入数组类型不正确直接返回

return S_OK;

try

{

longdim1=SafeArrayGetDim(lstCode.parray);

longdim2=SafeArrayGetDim(lstValue.parray);

long ubound;

long lbound;

SafeArrayGetUBound(lstCode.parray,dim1,&ubound);

SafeArrayGetLBound(lstCode.parray,dim1,&lbound);

BSTR* buf1,*buf2;

SafeArrayAccessData(lstCode.parray,(void**)&buf1);

SafeArrayAccessData(lstValue.parray,(void**)&buf2);

for(int i=lbound;i<ubound-lbound+1;i++)

{

vParam[1] =CComVariant(buf1[i]);

vParam[0] =CComVariant(buf2[i]);

**************此处省略若干业务相关代码************************

}

SafeArrayUnaccessData(lstCode.parray);// slove the delphiproblem "variant or safe array is locked"

SafeArrayUnaccessData(lstValue.parray);

*pVal =VARIANT_TRUE;

}

catch(...)

{

*pVal =VARIANT_FALSE;

return S_OK;

}

}

returnS_OK;

}

经过修改后,对于js或其他语言传递的数组该接口都可以正确运行


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值