Передача объекта в JScript из ActiveX (C++)
От: WizardOZ  
Дата: 10.03.10 08:27
Оценка:
Здравствуйте.
Есть проект ActiveX компонента реализованного на C++ (ATL). Работа с компонентом осуществляется из JavaScript.
Компонент содержит два класса Geometry и Shape. В классе Geometry есть метод getShape, который должен возвращать объект Shape, соответственно ожидается что после его вызова мы сможем считать свойства объекта из JavaScript.

Содержимое idl:
import "oaidl.idl";
import "ocidl.idl";

[
    object,
    uuid(80301D49-1F63-4FE5-9C5F-11074064A481),
    dual,
    oleautomation,
    nonextensible,
    helpstring("IShape Interface"),
    pointer_default(unique)
]
interface IShape : IDispatch{
    [propget, id(1), helpstring("property Description")] HRESULT Description([out, retval] BSTR* pVal);
    [propput, id(1), helpstring("property Description")] HRESULT Description([in] BSTR newVal);
};

[
    object,
    uuid(58845FA0-789C-4681-898B-5E419986DDC3),
    dual,
    oleautomation,
    nonextensible,
    helpstring("IGeometry Interface"),
    pointer_default(unique)
]
interface IGeometry : IDispatch{
    [id(1), helpstring("method getShape")] HRESULT getShape([out,retval] VARIANT* vtShape);
};

[
    uuid(9BBDB8B7-E44E-44A4-96E0-B80472E42876),
    version(1.0),
    helpstring("ATLActiveX 1.0")
]
library ATLActiveXLib
{
    importlib("stdole2.tlb");
    [
        uuid(11BAE8DC-D8C7-4BEF-B848-73FF6900611C),
        helpstring("Geometry Class")
    ]
    coclass Geometry
    {
        [default] interface IGeometry;
    };

    [
        uuid(3BDE7C3B-E0B7-423E-9821-C74D39140752),
        noncreatable,
        helpstring("Shape Class")
    ]
    coclass Shape
    {
        [default] interface IShape;
    };
};


Реализация метода getShape:
STDMETHODIMP CGeometry::getShape(VARIANT* vtShape)
{
    HRESULT h_result = S_OK;
    CComObject<CShape>* pShapeClass;

    VariantInit(vtShape);
    vtShape->vt = VT_DISPATCH;

    h_result = CComObject<CShape>::CreateInstance(&pShapeClass);
    if (SUCCEEDED(h_result)){
        pShapeClass->put_Description(SysAllocString(L"Описание для фигуры"));
        pShapeClass->QueryInterface(IID_IDispatch, (void**)&vtShape->pdispVal);
    }

    return h_result;
}


страница HTML для тестирования:

<html>
<head> 
    <title>JScript ActiveX</title> 
</head>
<SCRIPT LANGUAGE="JavaScript">
                
        function getshape()
        {                                
            try {
                var dll = new ActiveXObject("ATLActiveX.Geometry");
                var shape = dll.getShape();
                alert(shape.Description);
            }
            catch(e){
                alert(e.Message);
            }
        }
</SCRIPT>        
<body>
<input type="button" onclick="getshape();" value="Выполнить">
</body>
</html>


сам проект

В таком виде на первый взгляд все работает. Но после обращения к полю объекта, при обновлении страницы вылетает IE.
Подскажите как можно исправить данную ситуацию? Есть ли альтернативные способы передачи объекта в JavaScript?
Re: Передача объекта в JScript из ActiveX (C++)
От: Vi2 Удмуртия http://www.adem.ru
Дата: 10.03.10 08:51
Оценка:
Здравствуйте, WizardOZ, Вы писали:

WOZ>сам проект


WOZ>В таком виде на первый взгляд все работает. Но после обращения к полю объекта, при обновлении страницы вылетает IE.

WOZ>Подскажите как можно исправить данную ситуацию? Есть ли альтернативные способы передачи объекта в JavaScript?

STDMETHODIMP CShape::get_Description(BSTR* pVal)
{
    *pVal = desc;
    return S_OK;
}

STDMETHODIMP CShape::put_Description(BSTR newVal)
{
    desc = newVal;
    return S_OK;
}

с таким определением
class ATL_NO_VTABLE CShape : ...
{
public:
    BSTR desc;
...

никуда не годится, потому что нарушаются права владения строкой. desc должен владеть собственной копией, а не полученной от клиента через put_Description. Поэтому и код в CGeometry::getShape не верен.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[2]: Передача объекта в JScript из ActiveX (C++)
От: SuhanovSergey  
Дата: 10.03.10 11:19
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>никуда не годится, потому что нарушаются права владения строкой. desc должен владеть собственной копией, а не полученной от клиента через put_Description. Поэтому и код в CGeometry::getShape не верен.


И это
pShapeClass->put_Description(SysAllocString(L"Описание для фигуры"));


заменить
pShapeClass->put_Description(L"Описание для фигуры");
Re[3]: Передача объекта в JScript из ActiveX (C++)
От: Vi2 Удмуртия http://www.adem.ru
Дата: 10.03.10 11:25
Оценка:
Здравствуйте, SuhanovSergey, Вы писали:

SS>И это

SS>pShapeClass->put_Description(SysAllocString(L"Описание для фигуры"));

SS>заменить
SS>pShapeClass->put_Description(L"Описание для фигуры");

Позволю не согласиться, потому что L"Описание для фигуры" != SysAllocString(L"Описание для фигуры"), но SysAllocString(L"Описание для фигуры") == CComBSTR(L"Описание для фигуры") без потери памяти.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[4]: Передача объекта в JScript из ActiveX (C++)
От: SuhanovSergey  
Дата: 10.03.10 11:30
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Здравствуйте, SuhanovSergey, Вы писали:


SS>>И это

Vi2>
SS>>pShapeClass->put_Description(SysAllocString(L"Описание для фигуры"));
Vi2>

SS>>заменить
Vi2>
SS>>pShapeClass->put_Description(L"Описание для фигуры");
Vi2>

Vi2>Позволю не согласиться, потому что L"Описание для фигуры" != SysAllocString(L"Описание для фигуры"), но SysAllocString(L"Описание для фигуры") == CComBSTR(L"Описание для фигуры") без потери памяти.

Согласен.
Re[2]: Передача объекта в JScript из ActiveX (C++)
От: WizardOZ  
Дата: 11.03.10 08:37
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>
Vi2>STDMETHODIMP CShape::get_Description(BSTR* pVal)
Vi2>{
Vi2>    *pVal = desc;
Vi2>    return S_OK;
Vi2>}

Vi2>STDMETHODIMP CShape::put_Description(BSTR newVal)
Vi2>{
Vi2>    desc = newVal;
Vi2>    return S_OK;
Vi2>}
Vi2>

Vi2>с таким определением
Vi2>
Vi2>class ATL_NO_VTABLE CShape : ...
Vi2>{
Vi2>public:
Vi2>    BSTR desc;
Vi2>...
Vi2>

Vi2>никуда не годится, потому что нарушаются права владения строкой. desc должен владеть собственной копией, а не полученной от клиента через put_Description. Поэтому и код в CGeometry::getShape не верен.


Подскажите пожалуйста каким образом нужно объявить кокласс?. Просто с COM моделью познакомился недавно, и все это программирование на основе интерфейсом мне еще не до конца понятно. Можно ли как-то по другому передать объект в JavaScript? И если возможно, то хотя бы какой-нибудь небольшой пример для понимания процесса.
Re[3]: Передача объекта в JScript из ActiveX (C++)
От: Vi2 Удмуртия http://www.adem.ru
Дата: 11.03.10 10:00
Оценка:
Здравствуйте, WizardOZ, Вы писали:

WOZ>Подскажите пожалуйста каким образом нужно объявить кокласс?. Просто с COM моделью познакомился недавно, и все это программирование на основе интерфейсом мне еще не до конца понятно. Можно ли как-то по другому передать объект в JavaScript? И если возможно, то хотя бы какой-нибудь небольшой пример для понимания процесса.


Да вроде с коклассом у тебя всё в порядке (ну или относительно всё в порядке, поскольку идеал в коде не достижим). Проблема в реализации свойства. Вот приемлемый вариант (для BSTR desc:
STDMETHODIMP CShape::get_Description(/*[out,retval]*/ BSTR* pVal)
{
//    *pVal = desc;
    *pVal = SysAllocString(desc); // делаем копию и передаем клиенту
    return S_OK;
}

STDMETHODIMP CShape::put_Description(/*[in]*/ BSTR newVal)
{
//    desc = newVal;
    desc = SysAllocString(newVal); // делаем копию и сохраняем у себя
    return S_OK;
}

Посмотри Передача BSTR в ActiveX компонент на VC++ 6
Автор: EM
Дата: 04.05.04
или поищи на сайте слова "in out клиент сервер" для более полной информации.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[4]: Передача объекта в JScript из ActiveX (C++)
От: WizardOZ  
Дата: 15.03.10 02:05
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Здравствуйте, WizardOZ, Вы писали:


WOZ>>Подскажите пожалуйста каким образом нужно объявить кокласс?. Просто с COM моделью познакомился недавно, и все это программирование на основе интерфейсом мне еще не до конца понятно. Можно ли как-то по другому передать объект в JavaScript? И если возможно, то хотя бы какой-нибудь небольшой пример для понимания процесса.


Vi2>Да вроде с коклассом у тебя всё в порядке (ну или относительно всё в порядке, поскольку идеал в коде не достижим). Проблема в реализации свойства. Вот приемлемый вариант (для BSTR desc:

Vi2>
Vi2>STDMETHODIMP CShape::get_Description(/*[out,retval]*/ BSTR* pVal)
Vi2>{
Vi2>//    *pVal = desc;
Vi2>    *pVal = SysAllocString(desc); // делаем копию и передаем клиенту
Vi2>    return S_OK;
Vi2>}

Vi2>STDMETHODIMP CShape::put_Description(/*[in]*/ BSTR newVal)
Vi2>{
Vi2>//    desc = newVal;
Vi2>    desc = SysAllocString(newVal); // делаем копию и сохраняем у себя
Vi2>    return S_OK;
Vi2>}
Vi2>

Vi2>Посмотри Передача BSTR в ActiveX компонент на VC++ 6
Автор: EM
Дата: 04.05.04
или поищи на сайте слова "in out клиент сервер" для более полной информации.


Спасибо огромное. Протестировал работу в IE 6.0, 8.0, полет нормальный.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.