Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Передача объекта Array в COM - метод 
:(
    Опции темы
log584
Дата 22.12.2010, 20:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 2.1.2010

Репутация: нет
Всего: нет



Есть JScript - скрипт, запускаемый под IIS 5.0. В скрипте создается объект,  реализуемый в проекте ATL на VSC++ 2008.
Код

    var MyForm = Server.CreateObject("CMYASP.HTMLForm");
    var arr = new Array(23, 14, 35, 67);
    MyForm.Items = arr;

Как видно, созданный в скрипте объект типа Array присваивается свойству. Дальше.
Ловлю данный объект на стороне сервера:
Код

STDMETHODIMP CHTMLForm::put_Items(VARIANT * vParam)
{
    IDispatch * pDisp = vParam->pdispVal;
    return( S_OK );
}

vParam->vt = 9 = VT_DISPATCH.
А вот что это за IDispatch конкретно я не знаю. Соответственно и работать с ним далее не получается.
В этом собственно, и весь вопрос. Как узнать что это за тип, что бы знать его методы. В инете информации о интерфейсах объекта JScript Array я не нашел, пролазил два дня. Помогите пожалуйста.
PM MAIL   Вверх
jonie
Дата 23.12.2010, 09:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 5
Всего: 118



Код

// In *.idl file 
[propget, id(0)] HRESULT ArrayProperty([out, retval] SAFEARRAY(VARIANT) *pArray);
[propput, id(0)] HRESULT ArrayProperty([in] SAFEARRAY(VARIANT) Array);


// Somewhere in javascript

function ax2js(axArray) {    
    return new VBArray(array).toArray();
}

function js2ax(jsArray) {
    var dict = new ActiveXObject("Scripting.Dictionary");

    for (var i = 0; i < jsArray.length; i++) {
        dict.add(i, jsArray[i]);
    }

    return dict.Items();
}

function fooHandler() {
    var ax = new ActiveXObject("My.My");

    var ar = ax2js(ax.ArrayProperty);

    ax.ArrayProperty = js2ax(ar);
}



© отсюда: http://stackoverflow.com/questions/1926723...4345682#4345682


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
xvr
Дата 23.12.2010, 10:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 6984
Регистрация: 28.8.2007
Где: Химки, Московская обл

Репутация: 8
Всего: 222



Цитата(log584 @  22.12.2010,  20:56 Найти цитируемый пост)
Как узнать что это за тип, что бы знать его методы.
Array вестимо  smile 

Цитата(log584 @  22.12.2010,  20:56 Найти цитируемый пост)
В инете информации о интерфейсах объекта JScript Array я не нашел, пролазил два дня. Помогите пожалуйста. 

Помогаю - http://msdn.microsoft.com/en-us/library/k4...v=VS.85%29.aspx
А индексировать его можно попробовать через DISPID_VALUE (с параметром)

Добавлено через 11 минут и 35 секунд
Update - данные, помещенные в массив становятся доступны по имени, совпадающим с числом:
Код

1> a=([1,2,3]);
1,2,3
1> Info(a)
DISPATCH: 1,2,3

Supported interfaces:
IUnknown
IDispatch
IDispatchEx

Supported methods/properties (IDispatchEx):
 0
 1
 2
 valueOf
 toString
 length
1> a[5]=10
10
1> Info(a)
DISPATCH: 1,2,3,,,10

Supported interfaces:
IUnknown
IDispatch
IDispatchEx

Supported methods/properties (IDispatchEx):
 0
 1
 2
 valueOf
 toString
 length
 5
1>


PM MAIL   Вверх
log584
Дата 23.12.2010, 18:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 2.1.2010

Репутация: нет
Всего: нет



Цитата

Array вестимо

Да понятно, что не FileSystemObject. С объектом JScript Array я уже давно ознакомился в MSDN на локальной машине. xvr, на странице, в которую ты указал, описывается именно объект, используемый на стороне клиента автоматизации, а вот какой интерфейс использовать для доступа к методам кокласса данного объекта, на стороне C++, реализации COM сервера? Вот, может быть я изначально неточно сформулировал вопрос, извините.

jonie, по - моему, года два назад у меня уже была подобная ситуация ( опять - же по - моему с помощью VBArray я и выкручивался), ладно, я попробую передавать COM  - серверу объект VBArray, должно получиться, но все равно - это изврат. Изначально вопрос стоял о том, что за интерфейс реализован коклассом объекта Array, передаваемого из JScript на сторону C++? С тем, чтобы посмотреть его документацию и использовать его (на стороне C++ COM - сервера). Вот это будет самый верный путь.
PM MAIL   Вверх
xvr
Дата 23.12.2010, 20:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 6984
Регистрация: 28.8.2007
Где: Химки, Московская обл

Репутация: 8
Всего: 222



Цитата(log584 @  23.12.2010,  18:59 Найти цитируемый пост)
а вот какой интерфейс использовать для доступа к методам кокласса данного объекта, на стороне C++, реализации COM сервера? 
Тот же самый. IDispatch с методами и пропертями, которые описанны на странице из MSDN.
Полный список реализуемых интерфейсов был на строках 7-9 в листинге моем сообщении

Цитата(log584 @  23.12.2010,  18:59 Найти цитируемый пост)
 попробую передавать COM  - серверу объект VBArray, 
Угу. К сожалению стандартный метод передачи массивов в ActiveX (SAFEARRAY) интерпретатор JS не поддерживает  smile 

Цитата(log584 @  23.12.2010,  18:59 Найти цитируемый пост)
Изначально вопрос стоял о том, что за интерфейс реализован коклассом объекта Array, передаваемого из JScript на сторону C++?
Все, что выходит из стандартных MS интерпретаторов не имеет какого то специального типа/интерфейса - они все обычные IDispatch (точнее IDispatchEx)


PM MAIL   Вверх
log584
Дата 23.12.2010, 23:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 2.1.2010

Репутация: нет
Всего: нет



Цитата

Тот же самый

Тот же самый - это какой? (Какой интерфейс для C++?) Еще раз вопрос конкретно, какой интерфейс, его наименование, заголовочный файл из MSDN для C++? Ну пускай не из MSDN...
Цитата

IDispatch с методами и пропертями, которые описанны на странице из MSDN.

Какие такие методы и пропертя мне дают IUnknown, IDispatch (или интерфейсы классов), чтобы я смог вызывать конкретные методы кокласса для данного интерфейса объека Array?

Да есть у меня IDispatch, который ни о чем еще не гововорит. IUnknown, IDispatch сами по себе не предназначены для получения информации о методах интерфейса. Да, еще, 
не реализован у моего объекта JScript Array, передаваемого на сторону C++ сервера интерфейс IDispatchEx!!! У объекта, переданного на сторону сервера, при попытке инстанциировать интерфейс типа IDispatchEx в HRESULT возвращается E_NOINTERFACE. ???????? И еще, скорей всего, как я понял Делфинарий?

Цитата

Угу. К сожалению стандартный метод передачи массивов в ActiveX (SAFEARRAY) интерпретатор JS не поддерживает

А вот это ценная информация. И все равно, что за объект я получаю на стороне сервера?

Может полный проект дать?

PM MAIL   Вверх
xvr
Дата 24.12.2010, 08:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 6984
Регистрация: 28.8.2007
Где: Химки, Московская обл

Репутация: 8
Всего: 222



Цитата(log584 @  23.12.2010,  23:56 Найти цитируемый пост)
Какие такие методы и пропертя мне дают IUnknown, IDispatch (или интерфейсы классов), чтобы я смог вызывать конкретные методы кокласса для данного интерфейса объека Array?
IDispatch::GetIDSOfNames & IDispatch::Invoke

Цитата(log584 @  23.12.2010,  23:56 Найти цитируемый пост)
IDispatch сами по себе не предназначены для получения информации о методах интерфейса.
Ничего не путаете? IDispatch был сделан ИМЕННО ДЛЯ ЭТОГО!

Цитата(log584 @  23.12.2010,  23:56 Найти цитируемый пост)
У объекта, переданного на сторону сервера,
Вы хотели сказать - клиенту на С++? Т.к. сервер находится как раз внутри JS интерпретатора

Цитата(log584 @  23.12.2010,  23:56 Найти цитируемый пост)
при попытке инстанциировать интерфейс типа IDispatchEx в HRESULT возвращается E_NOINTERFACE.
Значит как то не так просили. Надо через QueryInterface


Цитата(log584 @  23.12.2010,  23:56 Найти цитируемый пост)
И все равно, что за объект я получаю на стороне сервера?
IDispatch. НЕ DUAL, ПРОСТОЙ IDispatch.


Цитата(log584 @  23.12.2010,  23:56 Найти цитируемый пост)
Может полный проект дать?

Вот, кусок из реального проекта:
Код

static void invoke_aux(IDispatch* dsp, wchar_t* name, WORD flags, Variant &v)
{
 DISPID disp;
 if (dsp->GetIDsOfNames(IID_NULL,&name,1,LOCALE_SYSTEM_DEFAULT,&disp)<0)
  {
   if (flags&DISPATCH_PROPERTYPUT) throw Exception("JS: Can't set property '"+AnsiString(name)+"' for aux object");
   v.Clear();
   return;
  }
 DISPPARAMS dparams;
 dparams.rgdispidNamedArgs=NULL;
 dparams.cNamedArgs=0;
 VARIANT* rv;
 if (flags&DISPATCH_PROPERTYPUT)
  {
   dparams.rgvarg=(VARIANT*)&v;
   dparams.cArgs=1;
   rv=NULL;
  }
 else
  {
   dparams.rgvarg=NULL;
   dparams.cArgs=0;
   rv=(VARIANT*)&v;
  }
 UINT err;
 if (dsp->Invoke(disp,IID_NULL,LOCALE_SYSTEM_DEFAULT,flags,&dparams,rv,NULL,&err)<0)
  throw Exception("JS: IDIspatch::Invoke falure on aux object (property '"+AnsiString(name)+"')");
}
Вызов из поданного IDispatch (dsp) метода/проперти по имени (name). Результат в v
В качестве имени используйте строку с индексом, (для индексации индексом 5 делайте так):
Код

Variant val;
invoke_aux(dsp,L"5", DISPATCH_PROPERTYGET,val);


PM MAIL   Вверх
log584
Дата 24.12.2010, 18:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 2.1.2010

Репутация: нет
Всего: нет



Спасибо, дошло. Но все равно это не решение. Какой объект, в таком случае я должен создать на стороне C++ сервера, чтобы он, попав на сторону скрипта, там в скрипте имел тип Array?
PM MAIL   Вверх
xvr
Дата 24.12.2010, 21:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 6984
Регистрация: 28.8.2007
Где: Химки, Московская обл

Репутация: 8
Всего: 222



Цитата(log584 @ 24.12.2010,  18:44)
Какой объект, в таком случае я должен создать на стороне C++ сервера, чтобы он, попав на сторону скрипта, там в скрипте имел тип Array?

В JS все объекты равноправны. А Array - это всего лишь один из встроенных объектов. Так что можно сделать IDispatch, который будет реализовывать методы Array, такой объект будет практически неотличим от родного JS Array'я. Полнофункциональный JS Array можно создать только внутри самого интерпретатора JS. Например попросив интерпретатор вычислить выражение  new Array() или просто ([]), в результате будет возвращен VARIANT, содержащий IDispatch настоящего JS Array'я. А дальше его можно наполнять данными (через IDispatchEx::GetDispID c fdexNameEnsure)


PM MAIL   Вверх
log584
Дата 24.12.2010, 22:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 2.1.2010

Репутация: нет
Всего: нет



Ладно, с этим разобрался. Спасибо большое за терпение. Если появятся дополнительные, надеюсь можно будет обратиться за помощью?

Это сообщение отредактировал(а) log584 - 24.12.2010, 22:20
PM MAIL   Вверх
xvr
Дата 25.12.2010, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 6984
Регистрация: 28.8.2007
Где: Химки, Московская обл

Репутация: 8
Всего: 222



Цитата(log584 @  24.12.2010,  22:15 Найти цитируемый пост)
Если появятся дополнительные, надеюсь можно будет обратиться за помощью?

Конечно

PM MAIL   Вверх
log584
Дата 25.12.2010, 21:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 2.1.2010

Репутация: нет
Всего: нет



Опять проблема. Если я правильно понял, то динамический создать элементы объекта массива на стороне COM - метода в виде индексированных свойств объекта можно только с помощью IDispatchEx. Если так, то нужно знать CLSID кокласса, реализующего IDispatchEx. А какой такой есть кокласс, задача которого реализовывать методы интерфейса IDispatchEx и больше ничего.
Или же искать любой другой CLSID, который реализует IDispatchEx. Но так не рационально вообще. В инете опять же я что - то через яндекс инфу не нашел. При попытке создать объект с интерфейсом IDispatchEx в возвращаемом HRESULT - 0x80040154 "Класс не зарегистрирован". Так как же мне все - таки его создать? Ведь основная идея в том, что бы создать обект массива в COM - методе, который будет передан JScript  скрипту.
Данный вопрос поднимался на rsnd, а как практически это сделать никто не указал.

Это сообщение отредактировал(а) log584 - 25.12.2010, 22:09
PM MAIL   Вверх
xvr
Дата 27.12.2010, 21:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 6984
Регистрация: 28.8.2007
Где: Химки, Московская обл

Репутация: 8
Всего: 222



Цитата(log584 @  25.12.2010,  21:57 Найти цитируемый пост)
Опять проблема. Если я правильно понял, то динамический создать элементы объекта массива на стороне COM - метода в виде индексированных свойств объекта можно только с помощью IDispatchEx. Если так, то нужно знать CLSID кокласса, реализующего IDispatchEx. А какой такой есть кокласс, задача которого реализовывать методы интерфейса IDispatchEx и больше ничего.
Не понял - вам нужно получить IDispatchEx или создать? Если первое, то банальный IDispatch::QueryInterface(IID_DispatchEx,...). Если второе - то либо поручить это JS интерпретатору (через IActiveScriptParse::ParseScriptText("new Array()") ), либо имплементировать самому (с нуля)



PM MAIL   Вверх
log584
Дата 28.12.2010, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 2.1.2010

Репутация: нет
Всего: нет



Вот код:
Код

STDMETHODIMP CHTMLForm::get_Items(VARIANT * vItems)
{
    HRESULT hr;
    CComPtr<IActiveScript> pActScp;
    IActiveScriptParse * pActScpPrs;

    hr = pActScp.CoCreateInstance(__uuidof(CLSID_JScript));//S_OK
    if(FAILED(hr)){
        vItems->vt = VT_EMPTY;
        return( S_OK );
    }

    hr = pActScp->QueryInterface(__uuidof(IActiveScriptParse), (void **)&pActScpPrs);//S_OK
    if(FAILED(hr)){
        vItems->vt = VT_EMPTY;
        return( S_OK );
    }

    hr = pActScpPrs->InitNew();//S_OK

    VARIANT vResult;
    EXCEPINFO excinf = {0};

    //E_UNEXPECTED
    hr = pActScpPrs->ParseScriptText(OLESTR("new Array();"), NULL, NULL, NULL, NULL, NULL, SCRIPTTEXT_ISVISIBLE, &vResult, &excinf);//E_UNEXPECTED

    return( hr );
}

Что нет может быть так? Обязательно ли реализовывать IActiveScriptSite?
Код

    IActiveScript::SetScriptSite(IActiveScriptSite *pScriptSite);


Это сообщение отредактировал(а) log584 - 28.12.2010, 17:24
PM MAIL   Вверх
xvr
Дата 28.12.2010, 22:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 6984
Регистрация: 28.8.2007
Где: Химки, Московская обл

Репутация: 8
Всего: 222



Цитата(log584 @  28.12.2010,  17:13 Найти цитируемый пост)
Что нет может быть так?
Интерпретатор не переведен в запущенное состояние (IActiveScript::SetScriptState(SCRIPTSTATE_STARTED))
Цитата(log584 @  28.12.2010,  17:13 Найти цитируемый пост)
Обязательно ли реализовывать IActiveScriptSite?
Обязательно.
Вот код инициализации JS интерпретатора (выдрано из рабочего проекта):
Код

void ObjectsHolder::find_js_engine()
{
 USES_CONVERSION;
 HKEY  key;
 DWORD sz=1024, type;
 HRESULT hr;
 char buf[1024];
 CLSID js_clsid;

 if (RegOpenKeyEx(HKEY_CLASSES_ROOT,"JavaScript\\CLSID",0,KEY_READ,&key)!=ERROR_SUCCESS)
  throw Exception("JS: Can't open JavaScript key in Registry");
 if (RegQueryValueEx(key,"",NULL,&type,(unsigned char*)buf,&sz)!=ERROR_SUCCESS)
  {RegCloseKey(key); throw Exception("JS: Can't get JavaScript key from Registry");}
 RegCloseKey(key);

 hr=CLSIDFromString(A2W(buf),&js_clsid);
 if (!SUCCEEDED(hr))
  throw Exception("JS: Invalid format of CLSID of JavaScript Script Engine");

 hr=CoCreateInstance(js_clsid,0,CLSCTX_INPROC_SERVER,IID_IActiveScript,(void**)&js_engine);
 if (!SUCCEEDED(hr))
  throw Exception("JS: Can't create JavaScript Scripting Engine");
 hr=js_engine->SetScriptSite((IActiveScriptSite*)this);
 if (!SUCCEEDED(hr)) throw Exception("JS: Can't set ScriptSite");
 {
  CComQIPtr<IActiveScriptParse,&IID_IActiveScriptParse> asp(js_engine);
  if (!asp) throw Exception("JS: Can't get interface to initialize JS engine");
  asp->InitNew();
 }
 hr=js_engine->SetScriptState(SCRIPTSTATE_STARTED);
 if (!SUCCEEDED(hr))
  throw Exception("JS: Can't start Script Engine");
}


По поводу ParseScriptText - в 7 параметр надо передать SCRIPTTEXT_ISEXPRESSION (SCRIPTTEXT_ISVISIBLE там необязателен)

Вот код для исполнения произвольной JS строки (Builder)
Код

HRESULT ObjectsHolder::js_execute(AnsiString script, Variant* rv)
{USES_CONVERSION;
 EXCEPINFO ex;
 if (script.IsEmpty()) return S_FALSE;
 CComQIPtr<IActiveScriptParse,&IID_IActiveScriptParse> asp(js_engine);
 if (!asp) throw Exception("JS: Can't get interface to load script code");  
 return asp->ParseScriptText(A2W(script.c_str()),NULL,NULL,NULL,0,0,rv?SCRIPTTEXT_ISEXPRESSION:0,(VARIANT*)rv,&ex);
}


PM MAIL   Вверх
Google
  Дата 20.5.2019, 15:29 (ссылка)  





  Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: COM/DCOM/ActiveX/ATL/CORBA | Следующая тема »


 




[ Время генерации скрипта: 0.1793 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.