Создание COM на VBScript, а использование на C++?
От: duan Россия  
Дата: 29.10.03 04:25
Оценка:
Создание COM на VBScript, а использование на C++? Помогите...

Создаю СОМ так:
Файл: coolOBJ.wsc


<?xml version="1.0"?>
<component id="duan">
    <registration
        description="coolOBJ"
        progid="coolOBJ"
        version="1.00"
        classid="{f87907b4-5595-49fd-96b2-bdce03fc85fd}"
    >
    </registration>
    
    <public>
        <method name="qd">
            <PARAMETER name="x"/>
        </method>
    </public>
    
    <script language="VBScript">
    <![CDATA[
        function qd(x)
            qd = x*x
        end function
    ]]>
    </script>
</component>



Регистрирую.
Cоздаю библиотеку типов: scriptlet.tlb.

VB (все работает):

' testCOM.vbs

Set component = CreateObject("coolOBJ")
MsgBox component.qd(2), 65, "MsgBox"



C++ (не работает. Почему???):

// testCOM.cpp

#import "scriptlet.tlb"

void _tmain(){
    CoInitialize( NULL );
    
    ScriptletTypeLib::AutomationPtr p;
       p.CreateInstance(L"coolOBJ"); // не работает
       
       p->qd(...    // естественно тоже не работает

     CoUninitialize();
}
Re: Использование на C++
От: Vi2 Удмуртия http://www.adem.ru
Дата: 29.10.03 05:18
Оценка:
Здравствуйте, duan, Вы писали:

D>C++ (не работает. Почему???):

D>// testCOM.cpp

D>#import "scriptlet.tlb"

D>void _tmain(){
D>    CoInitialize( NULL );
    
D>    ScriptletTypeLib::AutomationPtr p;
D>       p.CreateInstance(L"coolOBJ"); // не работает
       
D>      p->qd(...    // естественно тоже не работает

D>     CoUninitialize();
D>}

А код ошибки какой? И что не работает?
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[2]: C++ не работает
От: duan Россия  
Дата: 29.10.03 07:06
Оценка:
Здравствуйте, Vi2, Вы писали:


Vi2>

Vi2>А код ошибки какой? И что не работает?

p.CreateInstance возвращает -2147221005, а по идее должен 0 или больше

а если

cout << p;

то выдается 0, а если бы все было верно то такого не было

При использовании оператора "->" для p, выдается ассерт по отношению к "->"
т.е. нельзя вызвать никакую функцию через "->" например:

p->AnyFunction(...)

всегда приводит к Ассерт.

Вот это я имел в виду под "неработает"
Re[3]: C++ не работает
От: Left2 Украина  
Дата: 29.10.03 07:12
Оценка:
D>p.CreateInstance возвращает -2147221005, а по идее должен 0 или больше

Invalid ProgID.

Попробуй создавать по GUID
Если не получится — значит класс у тебя не зарегистрирован
Re[3]: C++ не работает
От: Vi2 Удмуртия http://www.adem.ru
Дата: 29.10.03 07:22
Оценка:
Здравствуйте, duan, Вы писали:

D>p.CreateInstance возвращает -2147221005, а по идее должен 0 или больше

Это
// MessageId: CO_E_CLASSSTRING
//
// MessageText:
//
//  Invalid class string
//
#define CO_E_CLASSSTRING                 _HRESULT_TYPEDEF_(0x800401F3L)

Попробуй p.CreateInstance(OLESTR("coolOBJ")); и просто p.CreateInstance("coolOBJ"); Что-то у тебя с настрйками в проекте. Или не зарегистрирован компонент. Посмотри в Реестре HKCR\coolOBJ.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re: Создание COM на VBScript, а использование на C++?
От: AlexeyP10  
Дата: 29.10.03 08:24
Оценка:
Может надо создавать:
duan.coolOBJ

Set component = CreateObject("duan.coolOBJ")

просто обычно имена объектов состоят из 2х частей (библиотека/объект, компания/объект), конечно можно и без этого, но мне кажется в данном случае логично.
... << RSDN@Home 1.1 beta 2 >>
Re[2]: Создание COM на VBScript, а использование на C++?
От: duan Россия  
Дата: 29.10.03 09:26
Оценка:
Здравствуйте, AlexeyP10, Вы писали:

AP>Может надо создавать:

AP>duan.coolOBJ

AP>Set component = CreateObject("duan.coolOBJ")


AP>просто обычно имена объектов состоят из 2х частей (библиотека/объект, компания/объект), конечно можно и без этого, но мне кажется в данном случае логично.


Я согласен.
Но что в данном случае имелось ввиду под duan. я несколько не понимаю?
Библиотека, компания ...???... А как все это на xml в vbs прописать
Re[4]: C++ не работает
От: duan Россия  
Дата: 29.10.03 09:29
Оценка:
Здравствуйте, Vi2, Вы писали:

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


Vi2>Попробуй p.CreateInstance(OLESTR("coolOBJ")); и просто p.CreateInstance("coolOBJ"); Что-то у тебя с настрйками в проекте. Или не зарегистрирован компонент. Посмотри в Реестре HKCR\coolOBJ.


Спасибо, за код об ошибке :-(

Но проблеммы это не снимает. С настройками все в порядке. А предложенные варианты не работают.

В реестре все в порядке
Re[4]: C++ не работает
От: duan Россия  
Дата: 29.10.03 09:33
Оценка:
Здравствуйте, Left2, Вы писали:

D>>p.CreateInstance возвращает -2147221005, а по идее должен 0 или больше


L>Invalid ProgID.


L>Попробуй создавать по GUID

L>Если не получится — значит класс у тебя не зарегистрирован

Я с COM знаком уже 2 дня, но я не понимаю что значит по GUID ;-)

Если имеется ввиду так:
DEFINE_GUID(CLSID_coolOBJ,
             0xF87907b4, 0x5595, 0x49fd, 0x96, 0xb2, 0xbd, 0xce, 0x03, 0xfc, 0x85, 0xfd);

// ...

p.CreateInstance(CLSID_coolOBJ);


То тоже не работает.

А класс зарегистрирован, ведь клиент на VB все видит и прекрасно работает.
А Вы сами попробуйте ;-)))
Re[3]: Создание COM на VBScript, а использование на C++?
От: AlexeyP10  
Дата: 29.10.03 10:05
Оценка:
<?XML version="1.0"?>
<component>
<registration>
   description="My Test Component"
   progid="Component.TestScript"
   version="1"
   classid="{2154c700-9253-11d1-a3ac-0aa0044eb5f}"
</registration>

<public>
   <property name="name"/>
   <method name="factorial"/>
</public>

<script language="VBScript">
   <![CDATA[
   Function factorial(n)
      If isNumeric(n) Then
         If n <= 1 Then
            factorial = 1
         Else
            factorial = n*factorial(n-1)
         End If
      Else
         factorial = -2   ' Error code.
      End If
   End Function
   ]]>
</script>
</component>


Вообщем вот кусок из MSDN, он точняк работает. Попробуй просто поименовать комонент как у них, мож поможет...
... << RSDN@Home 1.1 beta 2 >>
Re[4]: Создание COM на VBScript, а использование на C++?
От: duan Россия  
Дата: 29.10.03 12:32
Оценка:
Здравствуйте, AlexeyP10, Вы писали:


AP>Вообщем вот кусок из MSDN, он точняк работает. Попробуй просто поименовать комонент как у них, мож поможет...


Не работает :(

Изначально отсюда и начинал копать... ;) А потом msdn.com, codeguru.com, codeproject.com... Наконец решил на форуме спросить, когда ничего сам не смог
Re[5]: Создание COM на VBScript, а использование на C++?
От: George Seryakov Россия  
Дата: 29.10.03 14:52
Оценка:
Здравствуйте, duan, Вы писали:

AP>>Вообщем вот кусок из MSDN, он точняк работает. Попробуй просто поименовать комонент как у них, мож поможет...


D>Не работает


А у меня твой код, про который ты говоришь, что он не работает, — работает.

D>Изначально отсюда и начинал копать... А потом msdn.com, codeguru.com, codeproject.com... Наконец решил на форуме спросить, когда ничего сам не смог


Перегрузи машину. Переустанови винду. Попробуй на другой машине.
GS
Re[5]: Вот что есть
От: Vi2 Удмуртия http://www.adem.ru
Дата: 29.10.03 15:09
Оценка:
Здравствуйте, duan, Вы писали:

D>Но проблеммы это не снимает. С настройками все в порядке. А предложенные варианты не работают.
D>В реестре все в порядке

После выполнения твоего wsc
regsvr32 scrobj.dll /n /i:coolObj.wsc
rundll32.exe scrobj.dll,GenerateTypeLib -URL:coolObj.wsc

и включения в файл
#import "C:\FORUMS\scriptlet.tlb" named_guids

код
    ScriptletTypeLib::AutomationPtr p;
    p.CreateInstance(L"coolOBJ");

работает, т.е. объект нормально создается. Немного смущает сигнатура метода qd — он имеет vararg
Automation : IDispatch
{
    // Methods:
    _variant_t qd (const _variant_t & x,const _variant_t & OptionalArgs );

и я не смог выполнить код (вылет в catch с кодом _com_error::m_hresult == 0x800A01C2)
    _variant_t x(2.0);
    _variant_t OptionalArgs;
    _variant_t result = p->qd( x, OptionalArgs );

Но при помощи
    CComDispatchDriver pp( p );
    _variant_t result;
    hr = pp.Invoke1(0x1, &x, &result);

код нормально отработал и вернул result == {VT_R8, 4.0}.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[6]: Вот что есть
От: duan Россия  
Дата: 29.10.03 16:21
Оценка:
Здравствуйте, Vi2, Вы писали:

RULEZ. Спасибо за ответ. Чувствую после того как я наконец создам объект,
то CComDispatchDriver мне пригодится...

А пока... я ННЕЕННААВВИИЖЖУУ COM. Т.е. почему у всех заработал мой пример. И только у меня нет!!!???

Но буду разбираться.
Сегодня я уже три дня знаком с COM. :-)

Подскажите, если не трудно а зачем довесок в виде named_guids.
Я в MSDN смотрел, но не понял.
Re[6]: Создание COM на VBScript, а использование на C++?
От: duan Россия  
Дата: 29.10.03 16:26
Оценка:
Здравствуйте, George Seryakov, Вы писали:


GS>А у меня твой код, про который ты говоришь, что он не работает, — работает.

...
GS>Перегрузи машину. Переустанови винду. Попробуй на другой машине.

И у Vi2 работает. Блин. Но что то делать надо. Хотя это вопрос уже не для этого форума.

Машину перегружал. Так бывало у моего знакомого когда он плагин для ослика писал. Ему помогало. А мне нет. Завтра попробую на другой машине.
Re[7]: Вот что есть
От: Vi2 Удмуртия http://www.adem.ru
Дата: 30.10.03 04:41
Оценка:
Здравствуйте, duan, Вы писали:

D>А пока... я ННЕЕННААВВИИЖЖУУ COM. Т.е. почему у всех заработал мой пример. И только у меня нет!!!???

А что ты хочешь от трех дней знакомства
Проблема не в самом СОМ, а в некоторых аспектах использования СОМ. Нужно ОБЯЗАТЕЛЬНО регистрировать сервер.

Вот этот код не требует регистрации компонента wsc, но требует точного указания полного имени файла. Недостаток — вызов метода "qd" не зависит от реального описания, т.е. изменение в wsc может привести к неправильной работе кода.
    CComDispatchDriver pp;
    HRESULT hr = CoGetObject(OLESTR("script:C:/FORUMS/coolOBJ.wsc"),NULL, IID_IDispatch, (void **) &pp);
    CComVariant x(2.0);
    CComVariant result;
    hr = pp.Invoke1(OLESTR("qd"), &x, &resultx); // вызов "qd" по имени
//или    hr = pp.Invoke1(0x1, &x, &resultx); // вызов "qd" по номеру


D>Подскажите, если не трудно а зачем довесок в виде named_guids.

named_guids для именования всех GUIDов библиотеки — в файле tlh будет такая секция. Это просто осталось в строке. В твоем примере не мешает и не помогает.
//
// Named GUID constants initializations
//
extern "C" const GUID __declspec(selectany) LIBID_ScriptletTypeLib = ...
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[7]: Создание COM на VBScript
От: Vi2 Удмуртия http://www.adem.ru
Дата: 30.10.03 04:47
Оценка:
Здравствуйте, duan, Вы писали:

D>И у Vi2 работает. Блин. Но что то делать надо. Хотя это вопрос уже не для этого форума.

Ты бы написал, что ты делаешь по шагам. А так неясно, что ты делаешь неправильно. Или что не делаешь.

Потому как на vbs
Set component = CreateObject("coolOBJ")
эквивалентно
ScriptletTypeLib::AutomationPtr p(L"coolOBJ");

Если у одного клиента работает — объект создается, то у другого тоже должно. Чудес не бывает. Чем-то ситуации различаются.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[8]: Создание COM на VBScript
От: duan Россия  
Дата: 30.10.03 15:25
Оценка:
Здравствуйте, Vi2, Вы писали:

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


Vi2>

D>>И у Vi2 работает. Блин. Но что то делать надо. Хотя это вопрос уже не для этого форума.

Vi2>Ты бы написал, что ты делаешь по шагам. А так неясно, что ты делаешь неправильно. Или что не делаешь.

Vi2>Потому как на vbs

Vi2>Set component = CreateObject("coolOBJ")
Vi2>эквивалентно
Vi2>ScriptletTypeLib::AutomationPtr p(L"coolOBJ");

Я понимаю

Vi2>Если у одного клиента работает — объект создается, то у другого тоже должно. Чудес не бывает. Чем-то ситуации различаются.


Но создаю как и Вы. Абсотлютно так же.

regsvr32 scrobj.dll /n /i:coolObj.wsc
rundll32.exe scrobj.dll,GenerateTypeLib -URL:coolObj.wsc

(или можно правой кнопкой — результат тот же)

и так далее (как Вы писали)...

М-да. Но вообще говоря, все заработало ...на другой машине. Там VC 6.0 и Win98. А у меня XP SP1 VC7. На другой ХP SP1 VC7 результат такой же — 0. На w2k sp3 (VC не стоит) я не могу даже зарегистрировать COM. Чудеса?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.