Необходимо передать массив SAFEARRAY из ActiveX в JavaScript.
т.е. в скрипте это выглядит так:
alert(Control.Array[0])
Что должно вывести алерт со строкой в Array[0]
Соответственно у контрола есть метод
get_Arra(VARIANT *pVal)
{
///
}
Что должно быть внутри этого метода?
После некоторого поиска я понял, что массивы в JavaScript — это объекты, т.е.
получается надо реализовать какой-то класс, в котором будет отимплеменчен IDispatch обеспечивающий функцональность массива в JavaScript, или я не прав?
При обратной передаче из JS в ActiveX передается VARIANT c типом VT_DISPATCH. И элементы достаются
через pdispVal->Invoke()
Здравствуйте, subver, Вы писали:
S>Что должно быть внутри этого метода?
Создание соответствующего SAFEARRAY-я VARIANT-ов.
S>После некоторого поиска я понял, что массивы в JavaScript — это объекты, т.е. получается надо реализовать какой-то класс, в котором будет отимплеменчен IDispatch обеспечивающий функцональность массива в JavaScript, или я не прав?
В принципе, можно и так, но накладные расходы велики. Но можно при приеме обычного массива просто использовать конструкцию (или объект?) VBArray.
// создать массив
SAFEARRAY FAR *psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
// поместить в массив варианты
for (long index = 0; index < 3; index++ )
{
HRESULT hr = SafeArrayPutElement(psa1, &index, &varData[index]);
if( !SUCCEEDED(hr) )
break;
}
// обернуть массив в вариант
VariantInit(pVal); pVal->vt = VT_ARRAY|VT_VARIANT; pVal->parray = psa;
// потом не забыть удалить варианты и массив в клиенте
//for (int j = 0; j < 3; j++)
//{
// SysFreeString(varData[j].bstrVal);
//}
//SafeArrayDestroy(psa);
}
в VBScript все будет работать .....в JavaScript необходимо преобразовать массив :
var arrVB = MyControl.Array();
var arrJS = VBArray(arrVB).toArray();
Здравствуйте, subver, Вы писали:
S>Необходимо передать массив SAFEARRAY из ActiveX в JavaScript. S>т.е. в скрипте это выглядит так:
S>alert(Control.Array[0])
S>get_Arra(VARIANT *pVal) S>{ S> /// S>}
S>Что должно быть внутри этого метода?
S>После некоторого поиска я понял, что массивы в JavaScript — это объекты, т.е. S>получается надо реализовать какой-то класс, в котором будет отимплеменчен IDispatch обеспечивающий функцональность массива в JavaScript, или я не прав?
IDispatchEx, поскольку размерность массива определяется во время исполнения. Впрочем, если она фиксирована, то можно сделать и через IDispatch.
В IDispatchEx нужно заимплементить GetDispID() для "length" и индесов, и InvokeEx() для возращаемых таким образом dispid. Это минимум, достаточный для того, чтобы синтаксис Control.Array[0] сработал.
S>>После некоторого поиска я понял, что массивы в JavaScript — это объекты, т.е. получается надо реализовать какой-то класс, в котором будет отимплеменчен IDispatch обеспечивающий функцональность массива в JavaScript, или я не прав?
Vi2>В принципе, можно и так, но накладные расходы велики.
Откуда накладные расходы? Кроме того что это надо имлементить "ручками" больше никаких проблем не вижу. Более того, если бы нужно было поддерживать и VBScript и JScript и добиться максимального удобства для пользователя то этот вариант ИМХО самый лучший.
L>>Откуда накладные расходы? Кроме того что это надо имплементить "ручками" больше никаких проблем не вижу.
Vi2>Накладные расходы на round-trip каждого вызова за значением в объект. Конечно, можно избежать, но SAFEARRAY их изначально не имеет.
Имеешь в виду Invoke через IDispatch? Хотя — как их можно избежать непонятно...
Здравствуйте, Left2, Вы писали:
L>Откуда накладные расходы? Кроме того что это надо имлементить "ручками" больше никаких проблем не вижу. Более того, если бы нужно было поддерживать и VBScript и JScript и добиться максимального удобства для пользователя то этот вариант ИМХО самый лучший.
Я не уверен, что динамические объекты поддержатся вбскриптом. Может быть, можно тут же отдать массив по DISPID_GET_SAFEARRAY, но не пробовал.
Для скриптовой совместимости — васиковые массивы и VBArray.
Здравствуйте, George Seryakov, Вы писали:
GS>Здравствуйте, Left2, Вы писали:
L>>Откуда накладные расходы? Кроме того что это надо имлементить "ручками" больше никаких проблем не вижу. Более того, если бы нужно было поддерживать и VBScript и JScript и добиться максимального удобства для пользователя то этот вариант ИМХО самый лучший.
GS>Я не уверен, что динамические объекты поддержатся вбскриптом. Может быть, можно тут же отдать массив по DISPID_GET_SAFEARRAY, но не пробовал.
Что имеется в виду под динамическими обьектами? Я имел в виду — отдать обьект который будет иметь интерфейс IDispatch и имеет disp-методы Item, Count и т.п. В принципе, можно реализовать IEnumVariant — насколько я понимаю (буду благодарен если мне укажут насколько я прав) тогда будут работать VB-шные For-In и JS-ный Enumerator.
GS>Для скриптовой совместимости — васиковые массивы и VBArray.
Вроде бы уже сошлись на том что если вернуть SAFEARRAY(VARIANT) то будет работать ( ) и в VBS, и в JS (но в последнем случае юзеру будет неудобно обрабатывать результаты + я подозреваю солидные накладные расходы в случае возврата больших массивов на их копирование в JS-ный Array. Так что у меня всё же больше лежит душа к возврату обьекта ).
Кстати, в догонку — если посмотреть на большие обьектные модели от самих MS-овцев, то они тоже, похоже, предпочитают такое решение По крайней мере я не припомню возврата SAFEARRAY-ев из методов Word или Outlook.
L>Что имеется в виду под динамическими обьектами? Я имел в виду — отдать обьект который будет иметь интерфейс IDispatch и имеет disp-методы Item, Count и т.п. В принципе, можно реализовать IEnumVariant — насколько я понимаю (буду благодарен если мне укажут насколько я прав) тогда будут работать VB-шные For-In и JS-ный Enumerator.
Вспылил — реализовывать прийдётся сначала _NewEnum, а уж у возвращаемого им обьекта — IEnumVARIANT.
Здравствуйте, Left2, Вы писали:
GS>>Я не уверен, что динамические объекты поддержатся вбскриптом.
L>Что имеется в виду под динамическими обьектами? Я имел в виду — отдать обьект который будет иметь интерфейс IDispatch и имеет disp-методы Item, Count и т.п.
Имеется в виду IDispatchEx c disp пропертями '0', '1', ... заранее не определенное число. Или такое и с IDispatch можно сделать?
L>В принципе, можно реализовать IEnumVariant — насколько я понимаю (буду благодарен если мне укажут насколько я прав) тогда будут работать VB-шные For-In и JS-ный Enumerator.
Здравствуйте, Left2, Вы писали:
L>Имеешь в виду Invoke через IDispatch? Хотя — как их можно избежать непонятно...
Нет, не Invoke через IDispatch, потому что это так и так будет, а совпадением апартмента скрипта и объекта. Тогда затраты на вызов метода и доступ к элементу массива сравняются. Но нужно будет реализовывать коллекции и нумераторы, хотя это все и автоматизируется. Брр, проще передать SAFEARRAY.
GS>>>Я не уверен, что динамические объекты поддержатся вбскриптом.
L>>Что имеется в виду под динамическими обьектами? Я имел в виду — отдать обьект который будет иметь интерфейс IDispatch и имеет disp-методы Item, Count и т.п.
GS>Имеется в виду IDispatchEx c disp пропертями '0', '1', ... заранее не определенное число. Или такое и с IDispatch можно сделать?
С IDispatch такое сделать — вроде бы никаких проблем нет. Другое дело что я не уловил идею — зачем это нужно. Чтобы писать arr.0 = arr.1 ? Но я сомневаюсь что JScript такое поймёт.
L>>Имеешь в виду Invoke через IDispatch? Хотя — как их можно избежать непонятно...
Vi2>Нет, не Invoke через IDispatch, потому что это так и так будет, а совпадением апартмента скрипта и объекта. Тогда затраты на вызов метода и доступ к элементу массива сравняются. Но нужно будет реализовывать коллекции и нумераторы, хотя это все и автоматизируется. Брр, проще передать SAFEARRAY.
Насчёт апартмента согласен — если будет маршаллинг то тут издержки будут такие что проще SAFEARRAY перепихнуть один раз.
Здравствуйте, Left2, Вы писали:
GS>>Имеется в виду IDispatchEx c disp пропертями '0', '1', ... заранее не определенное число. Или такое и с IDispatch можно сделать?
L>С IDispatch такое сделать — вроде бы никаких проблем нет. Другое дело что я не уловил идею — зачем это нужно. Чтобы писать arr.0 = arr.1 ? Но я сомневаюсь что JScript такое поймёт.
Чтобы писать arr[0] = arr[1], в соответствии с дуальностью o.p — это то же самое что o['p']. arr.0, действительно, не понимает.
L>>С IDispatch такое сделать — вроде бы никаких проблем нет. Другое дело что я не уловил идею — зачем это нужно. Чтобы писать arr.0 = arr.1 ? Но я сомневаюсь что JScript такое поймёт.
GS>Чтобы писать arr[0] = arr[1], в соответствии с дуальностью o.p — это то же самое что o['p']. arr.0, действительно, не понимает.
Ух ты — не знал такого ... Вот уж век живи — век учись, спасибо!