我有一个托管Active Script JScript引擎的应用程序。根据jscript.dll的版本,它可以运行到JScript 5.8。该应用程序向JScript环境公开了许多对象和方法。
当脚本调用某个函数时,IDL如下:
HRESULT func(VARIANT varInput);
我想确定输入是否是instanceof
另一个函数(即,如果函数是一个构造函数,其原型在输入的原型链中)。在JScript中:
input instanceof Error
如何使用IDispatch / IDispatchEx在C ++中完成此操作?
该方法可以访问IActiveScript(由JScript引擎实现)和IActiveScriptSite(由主机实现)接口,因此可以使用IActiveScript :: GetScriptDispatch获取全局对象,其中任何其他构造函数(例如可以检索Error
)。
答案 0 :(得分:0)
您已包装到变体中的IDispatch*
具有DISPID_VALUE
(= 0
)属性,如果Error
对象将为您提供字符串值“[object]错误]”。
您还可以定义或注入JScript函数,如:
function IsInstanceOf(object, type) {
return object instanceof type;
}
function IsInstanceOfError(object) {
return IsInstanceOf(object, Error);
}
并使用IDispatch*
从您的C ++代码中调用它们,您已经按住它让JScript引擎根据特定类型对其进行检查,并返回此类检查的真/假结果。
答案 1 :(得分:0)
我认为Roman R是一个很好的答案,但是,为了最大限度地减少代码注入,您可以使用IActiveScriptParse::ParseScriptText
将任何匿名JavaScript函数转换为IDispatch
指针:
HRESULT hr = S_OK;
EXCEPINFO ei = { };
CComVariant vIsErrorFunc;
hr = spIActiveScriptParse->ParseScriptText(
OLESTR("(function () { return function (obj) { return obj instanceof Error; }; } )();"), // pstrCode
NULL, // pstrItemName
NULL, // punkContent
NULL, // pstrDelimiter
0, // dwSourceContextCookie
0, // ulStartingLineNumber
SCRIPTTEXT_ISEXPRESSION, // dwFlags
&vIsErrorFunc, // pvarResult
&ei // pexcepinfo
);
匿名函数方便地使用DISPID_VALUE
的DISPID,您可以使用IDispatch::Invoke
触发。如果VARIANT
中有JavaScript对象,则可以按如下方式对其进行测试:
// VARIANT* pvObject -- JavaScript object to test
DISPPARAMS dispParams = { pvObject, 0, 1, 0 };
CComVariant vResult;
hr = V_DISPATCH(&vIsErrorFunc)->Invoke(
DISPID_VALUE,
IID_NULL,
0,
DISPATCH_METHOD,
&dispParams,
&vResult,
NULL,
NULL);
你可以坚持vIsErrorFunc
,以便你可以重复使用匿名函数,或者你可以让它超出范围并让它被垃圾收集。无论哪种方式,都应该对JavaScript引擎中的客户端代码没有持久的影响。
**编辑:**
我发现我原来的匿名函数不起作用(我得到了VT_EMPTY而不是VT_DISPATCH):
function (obj) { return obj instanceof Error; }
为了欺骗它,我将函数包装如下:
(
function ()
{
return function (obj) { return obj instanceof Error; }
}
) ()
我希望这能解释我的例子中的奇怪表达。
答案 2 :(得分:-1)
与Java的instanceof运算符等效的C ++是使用dynamic_cast。 如,
x instanceof y
将在C ++中使用以下内容:
dynamic_cast<y*>(x) != 0