如何将JavaScript数组()转换为ATL/COM数组?
如何在不使用VBArray的情况下将JavaScript数组()转换为ATL/COM数组如何将JavaScript数组()转换为ATL/COM数组?,javascript,c++,arrays,atl,Javascript,C++,Arrays,Atl,如何在不使用VBArray的情况下将JavaScript数组()转换为ATL/COM数组 我想将一个新数组()转换为一个安全数组。我过去曾研究过这个问题,据我所知,这是不可能的。脚本中的唯一选项是使用VBScript和VBArray。javascript数组是包含IDispatch指针的变体。IDispatch实现在调度id处有一个枚举器方法 . 如果你使用C++,你也可以从对象中查询iQueXiFipe来访问它的元素。 < P>这里有一个代码要做(考虑到你已经把JS数组对象作为C++变量),与
我想将一个新数组()转换为一个安全数组。我过去曾研究过这个问题,据我所知,这是不可能的。脚本中的唯一选项是使用VBScript和VBArray。javascript数组是包含IDispatch指针的变体。IDispatch实现在调度id处有一个枚举器方法 .
如果你使用C++,你也可以从对象中查询iQueXiFipe来访问它的元素。 < P>这里有一个代码要做(考虑到你已经把JS数组对象作为C++变量),与<盛江> <强>的方式相同:
bool VariantToArray(__in const CComVariant& var, __out vector<CComVariant>& vecVars)
{
// convert variant to dispatch object
CComPtr<IDispatch> pDispatch = VariantToDispatch(var);
if (!pDispatch)
return false;
// invoke the object to retrieve the enumerator containing object
CComVariant varResult;
DISPPARAMS dispparamsNoArgs = {0};
EXCEPINFO excepInfo = {0};
UINT uiArgErr = (UINT)-1; // initialize to invalid arg
HRESULT hr = pDispatch->Invoke( DISPID_NEWENUM,
IID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_METHOD | DISPATCH_PROPERTYGET,
&dispparamsNoArgs,
&varResult,
&excepInfo,
&uiArgErr);
if (FAILED(hr))
return false;
// query the retrieved interface and get the enumerator object
CComPtr<IEnumVARIANT> pEnumVariant;
switch (varResult.vt)
{
case VT_UNKNOWN:
{
CComPtr<IUnknown> pUnknownResult = varResult.punkVal;
if (!pUnknownResult)
return false;
pEnumVariant = pUnknownResult; // implied query interface
}
break;
case VT_DISPATCH:
{
CComPtr<IDispatch> pDispatchResult = varResult.pdispVal;
if (!pDispatchResult)
return false;
pEnumVariant = pDispatchResult; // implied query interface
}
break;
default:
return false;
}
if (!pEnumVariant)
return false;
// reset enumerator to beginning of the list
hr = pEnumVariant->Reset();
if (FAILED(hr))
return false;
// enumerate and fetch items
CComVariant varItem;
ULONG uiFetched = 0;
do
{
// get next item
hr = pEnumVariant->Next(1, &varItem, &uiFetched);
if (FAILED(hr))
return false;
if (uiFetched == NULL) // last item
break;
// insert the item to the vector
vecVars.push_back(varItem);
} while (true);
return true;
}
bool VariantToArray(\uuuu in-const-CComVariant&var,\uuuu out-vector&vecVars)
{
//将变量转换为分派对象
CComPtr pDispatch=VariantotDispatch(var);
如果(!pDispatch)
返回false;
//调用该对象以检索包含该对象的枚举数
变异结果;
DISPPARAMS dispparamsNoArgs={0};
EXEPINFO EXEPINFO={0};
UINT uiArgErr=(UINT)-1;//初始化为无效参数
HRESULT hr=pDispatch->Invoke(dispatid\u NEWENUM,
IID_NULL,
区域设置\用户\默认值,
调度方法|调度属性集,
&disparamsnoargs,
&varResult,
&除此之外,
&uiArgErr);
如果(失败(小时))
返回false;
//查询检索到的接口并获取枚举器对象
CComPtr pEnumVariant;
开关(varResult.vt)
{
案例VT_未知:
{
CComPtr punnownresult=varResult.punkVal;
如果(!PunnownResult)
返回false;
pEnumVariant=pUnknownResult;//隐含查询接口
}
打破
案例VT_调度:
{
CComPtr pDispatchResult=varResult.pdispVal;
如果(!pDispatchResult)
返回false;
pEnumVariant=pDispatchResult;//隐含查询接口
}
打破
违约:
返回false;
}
如果(!pEnumVariant)
返回false;
//将枚举数重置为列表的开头
hr=pEnumVariant->Reset();
如果(失败(小时))
返回false;
//枚举和获取项目
变异变量;
ULONG uiFetched=0;
做
{
//获取下一项
hr=pEnumVariant->Next(1,&varItem,&uiFetched);
如果(失败(小时))
返回false;
if(uiFetched==NULL)//最后一项
打破
//将项目插入到向量中
向量推回(变量);
}虽然(正确);
返回true;
}
希望有帮助
注意:我看到一篇帖子,其中(但在IE6、7、8上是这样),我自己检查了一下——在IE9上(仅限)调用方法失败并返回DISP_E_异常。
所以我仍然在寻找更好的解决方案 编辑:
以下代码适用于所有IE浏览器:
bool VariantToArray(__in const CComVariant& var, __out vector<CComVariant>& vecVars)
{
// convert variant to dispatch object
CComPtr<IDispatch> pDispatch = VariantToDispatch(var);
if (!pDispatch)
return false;
// get DISPID of length parameter from array object
LPOLESTR sLengthName = L"length";
DISPID dispidLength = 0;
HRESULT hr = pDispatch->GetIDsOfNames(IID_NULL, &sLengthName, 1, LOCALE_USER_DEFAULT, &dispidLength);
if (FAILED(hr))
return false;
// get the number of elements using the DISPID of length parameter
CComVariant varLength;
DISPPARAMS dispParams = {0};
hr = pDispatch->Invoke(dispidLength, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispParams, &varLength, NULL, NULL);
if (FAILED(hr))
return false;
int nLength = 0; // length of the array
bool bGotInt = VariantToInt(varLength, nLength);
if (!bGotInt)
return false;
// get items of array
for (int i=0 ; i<nLength ; ++i)
{
// get DISPID of item[i] from array object
wstring strIndex = StringUtils::IntToString(i);
DISPID dispidIndex = 0;
LPOLESTR pIndex = reinterpret_cast<LPOLESTR>(const_cast<WCHAR *>(strIndex.data()));
hr = pDispatch->GetIDsOfNames(IID_NULL, &pIndex, 1, LOCALE_USER_DEFAULT, &dispidIndex);
if (FAILED(hr))
continue;
CComVariant varItem;
hr = pDispatch->Invoke(dispidIndex, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispParams, &varItem, NULL, NULL);
if (FAILED(hr))
continue;
vecVars.push_back(varItem);
}
return true;
}
bool VariantToArray(\uuuu in-const-CComVariant&var,\uuuu out-vector&vecVars)
{
//将变量转换为分派对象
CComPtr pDispatch=VariantotDispatch(var);
如果(!pDispatch)
返回false;
//从数组对象获取长度参数的DISPID
LPOLESTR SLENGHTNAME=L“长度”;
DISPID dispidleength=0;
HRESULT hr=pDispatch->GetIDsOfNames(IID_NULL,&slengtname,1,LOCALE_USER_DEFAULT,&dispatidlength);
如果(失败(小时))
返回false;
//使用DISPID of length参数获取元素数
变异变长;
DISPPARAMS DISPPARAMS={0};
hr=pDispatch->Invoke(dispatidlength,IID_NULL,LOCALE_USER_DEFAULT,DISPATCH_PROPERTYGET,&dispatchparams,&varLength,NULL,NULL);
如果(失败(小时))
返回false;
int nLength=0;//数组的长度
bool bGotInt=VariantToInt(varLength,nLength);
如果(!bgoint)
返回false;
//获取数组的项
对于(int i=0;iGetIDsOfNames(IID_NULL,&pIndex,1,LOCALE_USER_DEFAULT,&dispid索引);
如果(失败(小时))
继续;
变异变量;
hr=pDispatch->Invoke(dispatdindex,IID\u NULL,LOCALE\u USER\u DEFAULT,DISPATCH\u PROPERTYGET,&dispatchparams,&varItem,NULL,NULL);
如果(失败(小时))
继续;
向量推回(变量);
}
返回true;
}
< < /P> < P> > <代码> IActiveScript < /Cord> >您可以在C++中实例化JavaScript引擎,并将其用于:
- 为JavaScript函数生成
指针IDispatch*
- 生成包含JavaScript对象的
变量VARIANT
- 将JavaScript对象传递给C中的JavaScript函数++
函数(arr){return arr.length;}
IActiveScriptSite
。下面是一个演示这个概念的C++控制台应用程序:
// C++ headers for ATL and Active Script Hosting.
#include <atlbase.h>
#include <atlcom.h>
#include <activscp.h>
// A minimal implementation of IActiveScriptSite.
class ATL_NO_VTABLE CScriptSite :
public CComObjectRootEx<CComSingleThreadModel>,
public IActiveScriptSite,
public IActiveScriptSiteWindow
{
public:
BEGIN_COM_MAP(CScriptSite)
COM_INTERFACE_ENTRY(IActiveScriptSite)
COM_INTERFACE_ENTRY(IActiveScriptSiteWindow)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public:
// IActiveScriptSite
STDMETHOD(GetLCID)(LCID* plcid)
{
*plcid = 0;
return S_OK;
}
STDMETHOD(GetItemInfo)(
LPCOLESTR pstrName,
DWORD dwReturnMask,
IUnknown** ppiunkItem,
ITypeInfo** ppti)
{
return TYPE_E_ELEMENTNOTFOUND;
}
STDMETHOD(GetDocVersionString)(BSTR* pbstrVersion)
{
*pbstrVersion = ::SysAllocString(L"1.0");
return S_OK;
}
STDMETHOD(OnScriptTerminate)(
const VARIANT* pvarResult,
const EXCEPINFO* pexcepinfo)
{
return S_OK;
}
STDMETHOD(OnStateChange)(SCRIPTSTATE ssScriptState)
{
return S_OK;
}
STDMETHOD(OnScriptError)(IActiveScriptError* pIActiveScriptError)
{
return S_OK;
}
STDMETHOD(OnEnterScript)(void)
{
return S_OK;
}
STDMETHOD(OnLeaveScript)(void)
{
return S_OK;
}
// IActiveScriptSiteWindow
STDMETHOD(GetWindow)(HWND* phWnd)
{
*phWnd = NULL;
return S_OK;
}
STDMETHOD(EnableModeless)(BOOL fEnable)
{
return S_OK;
}
};
// ATL in a Console app.
CComModule _Module;
BEGIN_OBJECT_MAP(ObjectMap)
END_OBJECT_MAP()
// Main body
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = S_OK;
hr = _Module.Init(ObjectMap, NULL, NULL);
// Instantiate JavaScript engine.
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
CComObject<CScriptSite>* pScriptSite = NULL;
hr = CComObject<CScriptSite>::CreateInstance(&pScriptSite);
pScriptSite->AddRef();
CComPtr<IActiveScript> spIActiveScript;
hr = spIActiveScript.CoCreateInstance(OLESTR("JScript"));
hr = spIActiveScript->SetScriptSite(pScriptSite);
CComPtr<IActiveScriptParse> spIActiveScriptParse;
hr = spIActiveScript->QueryInterface(IID_IActiveScriptParse, (void **) &spIActiveScriptParse);
hr = spIActiveScriptParse->InitNew();
hr = spIActiveScript->SetScriptState(SCRIPTSTATE_CONNECTED);
// Evaluate an anonymous JavaScript function.
CComVariant vSomeFunc;
EXCEPINFO ei = { };
hr = spIActiveScriptParse->ParseScriptText(
OLESTR("(function () { return function (arr) { return arr.length; }; } )();"), // pstrCode
NULL, // pstrItemName
NULL, // punkContent
NULL, // pstrDelimiter
0, // dwSourceContextCookie
0, // ulStartingLineNumber
SCRIPTTEXT_ISEXPRESSION, // dwFlags
&vSomeFunc, // pvarResult
&ei // pexcepinfo
);
// Make a JavaScript array object.
CComVariant vObject;
hr = spIActiveScriptParse->ParseScriptText(
OLESTR("[2,3,5,7,11]"), // pstrCode
NULL, // pstrItemName
NULL, // punkContent
NULL, // pstrDelimiter
0, // dwSourceContextCookie
0, // ulStartingLineNumber
SCRIPTTEXT_ISEXPRESSION, // dwFlags
&vObject, // pvarResult
&ei // pexcepinfo
);
// Call the anonymous JavaScript function (gives answer of 5).
CComVariant vResult;
DISPPARAMS dispParams = { &vObject, 0, 1, 0 };
hr = V_DISPATCH(&vSomeFunc)->Invoke(
DISPID_VALUE,
IID_NULL,
0,
DISPATCH_METHOD,
&dispParams,
&vResult,
&ei,
NULL);
// Release variables.
hr = vSomeFunc.Clear();
hr = vObject.Clear();
hr = vResult.Clear();
// Release JavaScript engine.
spIActiveScriptParse = NULL;
spIActiveScript = NULL;
pScriptSite->Release();
pScriptSite = NULL;
::CoUninitialize();
return 0;
}
< ATL和活动脚本托管的代码> //C++标题。
#包括
#包括
#包括
//IActiveScriptSite的最小实现。
类别ATL_NO_VTABLE CScriptSite:
公共CComObjectRootEx,
公共活动描述网站,
公共IActiveScriptSiteWindow
{
公众:
开始COM地图(CScriptSite)
国际通信