У меня есть приложение, которое содержит движок Active Script JScript. В зависимости от версии jscript.dll, он работает до JScript 5.8. Приложение предоставляет множество объектов и методов среде JScript.
Когда скрипт вызывает определенную функцию, с IDL вот так:
HRESULT func(VARIANT varInput);
Я хочу определить, является ли вход instanceof
другая функция (то есть, если функция является конструктором, прототип которого находится в цепочке прототипов ввода). В JScript:
input instanceof Error
Как это можно сделать в C ++ с IDispatch / IDispatchEx?
У метода есть доступ к интерфейсам IActiveScript (реализованным движком JScript) и IActiveScriptSite (реализуемым хостом), поэтому можно получить глобальный объект с помощью IActiveScript :: GetScriptDispatch, из которого любой другой конструктор (такой как Error
) можно получить.
IDispatch*
вы завернули в вариант есть DISPID_VALUE
знак равно 0
) имущество, которое в случае Error
объект выдаст вам строковое значение «[ошибка объекта]».
Вы также можете определить или внедрить функции JScript, такие как:
function IsInstanceOf(object, type) {
return object instanceof type;
}
function IsInstanceOfError(object) {
return IsInstanceOf(object, Error);
}
и перезвоните из вашего кода C ++, используя IDispatch*
вы уже придерживаетесь того, чтобы механизм JScript проверил его по определенному типу и вернул вам результат проверки true / false.
Я думаю, что 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 DISPID_VALUE
который вы можете использовать IDispatch::Invoke
, Если у вас есть объект JavaScript в VARIANT
Вы можете проверить это следующим образом:
// 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_DISPATCH я получил VT_EMPTY):
function (obj) { return obj instanceof Error; }
Чтобы обмануть это, я обернул функцию следующим образом:
(
function ()
{
return function (obj) { return obj instanceof Error; }
}
) ()
Я надеюсь, что это объясняет странное выражение в моем примере.
С ++, эквивалентный оператору instanceof в Java, — использовать dynamic_cast.
например.,
x instanceof y
будет следующим в C ++:
dynamic_cast<y*>(x) != 0