Mathcad и OLE

Тема в разделе "WASM.WIN32", создана пользователем uni, 23 май 2005.

  1. uni

    uni New Member

    Публикаций:
    0
    Регистрация:
    23 май 2005
    Сообщения:
    67
    Доброго Вам и всех благ, участники форума.



    Пришёл я к вам с проблемой, суть которой до конца сам не понимаю, но надеюсь здесь помощь получить. Вы увидите, что программист я уже "искусанный", но видимо не достаточно. Перейдём к сути (я не сильно шуршал тут в поиске, но явного ответа на свой вопрос не нашёл).



    Задача. Поставил я её себе сам. Хочу создать cgi-приложение, которое использует библиотеки для работы с COM объектами. Я уже создавал простые cgi-приложения и запускал их под серверами, но при использовании COM возникли трудности, мною не предвиденные. Я сам вообще-то не пишу на асме, но пришлось себя заставить, чтобы докапаться до сути. Я обошелся бы возможностями php для работы с COM, но объект, экземпляр которого хочу я получить, не совсем "полноценный" COM объект. В том смысле, что php не может его отыскать. В общем и целом писал я много разного кода и не с бухты барахты сюда свалился.



    Что я хочу - есть у меня Apache 2 версии и захотел я воспользоваться движком Mathcad'а чтобы удалённо выполнять вычисления. Ну захотел и всё, конечно слышал про другие пакеты. Решил начать с простого. Консольные приложения для использования движка я уже сделал в Delphi и в C++Builder'е, но они не работают под сервером. По какой причине не могу понять и решил опуститься на уровень ассемблера, чтобы вызывать функции напрямую, без оболочек сред разработки. Сначала я захотел повторить консольное приложение на wasm:




    Код (Text):
    1. .data
    2. ; Имя класса должно быть в Unicode
    3. WSTR wszClassName, "Mathcad.Worksheet"
    4. ;wszClassName   wchar   L(<Mathcad.Worksheet\0>)
    5. psl     dd  0
    6. pmc     dd  0
    7. pWSs    dd  0
    8. CLSID_Module GUID <0>
    9. IID_NULL GUID <0, 0, 0, <0, 0, 0, 0, 0, 0, 0, 0>>
    10. IID_IDispatch GUID <000020400H, 00000H, 00000H, <0C0H, 000H, 000H, 000H, 000H, 000H, 000H, 046H>>
    11. sztempl db "Disp ID for 'Application' = %08X",0
    12. szCaption db "Тест",0
    13. rgszNames dd offset dwApp
    14. dwApp dw 'A','p','p','l','i','c','a','t','i','o','n', 0, 0, 0
    15. NameID dd 0
    16. pObj    dd  0
    17. szText  db  "Нулевой указатель", 0
    18. ;v1 VARIANT
    19.  
    20. .data?
    21. szBuffer db 400 dup (?)
    22. .code
    23. start:
    24.     invoke  CoInitialize, NULL
    25.     test    eax,eax
    26.     .if (!eax)
    27.         invoke  CLSIDFromProgID, offset wszClassName, addr CLSID_Module
    28.         invoke  CoCreateInstance, addr CLSID_Module, NULL, CLSCTX_INPROC_SERVER or \
    29.                  CLSCTX_LOCAL_SERVER, addr IID_IMathcadWorksheet, addr psl
    30. ;       coinvoke psl, IDispatch, QueryInterface, addr IID_IMathcadWorksheet, addr pObj
    31. ;       .if (!pObj)
    32. ;           invoke MessageBox, NULL, szText, addr szCaption, MB_OK
    33. ;       .endif
    34.         coinvoke psl, IMathcadWorksheet, Application, addr pmc
    35.         coinvoke pmc, IMathcadApplication, Set_Visible, 1
    36.         invoke  Sleep, 5000
    37.     .endif
    38. ; закрываем библиотеку COM
    39.     invoke CoUninitialize  
    40. exit:        
    41.     invoke ExitProcess, eax
    42. end start




    В описании из библиотки типов сказано по метод Set_Visible:
    Код (Text):
    1.     [id(0x0000000e), propput]
    2.     HRESULT Visible([in] VARIANT_BOOL bVal);
    3.     [id(0x0000000e), propget]
    4.     HRESULT Visible([out, retval] VARIANT_BOOL* bVal);




    Я вообще и сам разберусь, только подскажите как создать переменную типа Variant, сказать ей, что она содержит тип VARIANT_BOOL и присвоить значение TRUE.



    Получилось сумбурно. Я хотел написать больше, но передумал и решил по частям спрашивать. В отладчике я получаю идентификатор класса, процесс создается - вижу в окне процессов, для этого ввел sleep. Получить ссылку на экземпляр можно только вызовом Mathcad.Worksheet, а не Application (по крайней мере версии Mathcad 11.0a). Я пока мало знаком с технологиями, если бы можно было под отладчиком методы вызывать, может быть и разобрался бы, но приложение не запускается - проблемы с путями, не подгружаются библиотеки необходимые. Использую RadAsm & OllyDbg. Я думаю, что проблема с непониманием мною работы с типом Variant под masm.

    На языках высокого уровня при запуске консольного приложения в качестве cgi под веб сервером выдается ошибка, что класс не зарегистрировал или что-то в этом духе, хотя само по себе приложение работает.

    Извините за некоторую сумбурность изложения. Я вообще хочу хотя бы показать главное окно приложения используя masm.

    Ещё мне не очень понятен принцип использования coinvoke. А именно, когда я описываю методы, то сколько DWORD ов писать в зависимости от количества параметров и их отсутствия. Тут у меня не совсем полная ясность, примеры не очень помогли.
     
  2. uni

    uni New Member

    Публикаций:
    0
    Регистрация:
    23 май 2005
    Сообщения:
    67
    Видимо я спросил не так. Или непонятно чтО спросил. Если всё же кого-нибудь эта тематика заинтересует вот две ссылки на топики в другом форуме:

    http://www.exponenta.ru/forum/viewtopic.asp?t=2082

    http://www.exponenta.ru/forum/viewtopic.asp?t=2023



    Там приведены исходники консольных приложений на C++Builder'е и Delphi. Только форум не поддерживает аттачей в форме произольных файлов, так что мне пришлось выкручиваться. Как скачавать там есть краткое описание. Дублировать здесь, наверное нет необходимости. Эти консольные приложения сами по себе работают, а когда я оставляю вызов, допустим
    Код (Text):
    1. ws = CreateOleObject("Mathcad.Worksheet");


    и всё, то под сервером такое cgi приложение с добавкой
    Код (Text):
    1.  cout << "Content-type: text\/html \n\n";
    2.  cout << "<html> <body> Test! <\/body><\/html>";
    3.  
    конечно, не выдаёт этот текст, а в зависимости от вариантов вызова (напрямую, либо с помощью php) указывается ошибка. Самое интересное, когда я написал тоже самое на асме, т.е. только запросил ссылку CreateInstance(), то такое консольное приложение ошибок почему-то не вызывало. Это меня и сподвигло на написание cgi приложения на асме. Ну хотя бы понять в чем тут дело, может я рано радуюсь и как-то несовместимы мои желания.



    Я вообще хочу сделать что-то наподобие MAS - Mathcad Applications Server для себя. Попробую перефразировать свой вопрос на другом примере, который не потребует специализированного софта.