на главнуюВсе эхи RU.CBUILDER
войти ?

Глюк ATL 3.0 в С++ Builder 6.0

От Dmytry Ginzburg (2:461/48.125) к Vlad Foltz

В ответ на Заголовок предыдущего сообщения в треде (Имя Автора)


Здравствуйте, о моногоуважаемый(ая), Vlad!
Вот.. Hабил письмецо.. А вот, что из этого вышло:

Как-то, Вторник, Май 05 2009, в 20:57, Vlad Foltz приехал к Dmytry Ginzburg на белом лимузине, да как заорёт _"Глюк ATL 3.0 в С++ Builder 6.0"_

VF> Пpивет, Dmytry !

VF> Вт Maй 05 2009 22:21 по московскомy вpемени
VF> Dmytry Ginzburg написал к Vlad Foltz:

DG>> Про MFC спорить не буду. А вот COM-объект без ATL на билдере не
DG>> создашь.

VF> Hу тогда - дельфи. Или свой велосипед. ATL в билдере не рабочий
VF> совершенно, его "поддержка" - не более чем маркетинговая фишка. Сколько-то
VF> лет назад я сюда писал про это в подробностях. Там какие-то базовые вещи
VF> типа CComBSTR с багами...

Hу, строки использовать необязательно, можно пользоваться типом VARIANT. А вот с регистрацией действительно интересная ситуация получается. Я опишу, что я делал и буду рад комментарию. Интересно, правильно я понял логику ATL. Значит я создал консольный проект с поддержкой VCL. Добавляю в него RemoteDataModule. После этого мне билдер создал библиотеку типов, соответствующие h и cpp файлы, а также файл с расширением bpf. Этот файл имеет следующую структуру.
_!--==> А тута Windows Clipboard начинается... <==--!_
#include <atl\atlmod.h>
#include "MyServerImpl.h"
USEFORM("MyServerImpl.cpp", MyServer); /* TCRemoteDataModule: File Type */ /* MyServer: CoClass */
//---------------------------------------------------------------------------
This file is used by the project manager only and should be treated like the project file
// NOTE: You may derive a class from TComModule and use it as your server's
// module object. (i.e. Assign an instance of that class to _Module).
// However, you must *NOT* change the name _Module.
//
TComModule _ProjectModule(0 /*InitATLServer*/);
TComModule &_Module = _ProjectModule;

// The ATL Object map holds an array of _ATL_OBJMAP_ENTRY structures that
// described the objects of your OLE server. The MAP is handed to your
// project's CComModule-derived _Module object via the Init method.
//
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_MyServer, TMyServerImpl)
END_OBJECT_MAP()
//---------------------------------------------------------------------------
_!--==> А тута Windows Clipboard заканчивается... <==--!_
Как я понимаю, содержимое этого файла исполняется перед входом в функцию WinMain главного модуля программы. В нём создаётся объект типа TComModule. Покурив файлы библиотеки ATL, я увидел, что там есть метод, который регистрирует сервер в реестре, если это необходимо, а также регистрирует фабрику класса. Этот метод вызывается из Initproc, следовательно он должен автоматически исполняться ещё до вызова WinMain. А сам объект RemoteDataModule создаётся при вызове CreateInstance фабрики класса. Я решил взять потоковую модель tmFree. Тогда, как я понимаю, при обращению к моему объекту каждого отдельного клиента COM создаёт поток, в котором и идут вызовы. При отключении последнего клиента по идее RemoteDataModule удаляется из памяти вместе с объектом. Тогда определяю event.
_!--==> А тута Windows Clipboard начинается... <==--!_
HANDLE hEvent=CreateEvent(0,true,false,0);
_!--==> А тута Windows Clipboard заканчивается... <==--!_
В деструкторе моего объекта я его устанавливаю
_!--==> А тута Windows Clipboard начинается... <==--!_
void __fastcall TMyServer::CRemoteDataModuleDestroy(TObject *Sender)
{SetEvent(hEvent);

}
_!--==> А тута Windows Clipboard заканчивается... <==--!_
И тогда в WinMain мне остаётся только поставить функцию ожидания срабатывания события
_!--==> А тута Windows Clipboard начинается... <==--!_
WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{if(!strstr(lpCmdLine,"regserver")&&(!strstr(lpCmdLine,"unregserver")))WaitForS ingleObject(hEvent,INFINITE);
return 0;
}
_!--==> А тута Windows Clipboard заканчивается... <==--!_
Теперь вернёмся к регистрации сервера. Я решил попробовать пройти отладчиком по коду и выяснить, где происходит ошибка, при которой кокласс не записывается в реестр. При этом эксперт создал такой метод, который должен вызываться при регистрации

_!--==> А тута Windows Clipboard начинается... <==--!_
static HRESULT WINAPI UpdateRegistry(BOOL bRegister)
{
TRemoteDataModuleRegistrar regObj(GetObjectCLSID(), GetProgID(), GetDescription());
// Disable these flags in order to disable use by socket or web connections.
// Also set other flags to configure the behavior of your application server.
// For more information, see atlmod.h and atlvcl.cpp.
regObj.Singleton = true;
regObj.EnableWeb = true;
regObj.EnableSocket = true;
return regObj.UpdateRegistry(bRegister);
}
_!--==> А тута Windows Clipboard заканчивается... <==--!_
Я попытался поставить брекпоинты на этом методе, а также на реализованных мной методах, но при запуске с ключом /regserver из среды эти брекпоинты почему-то неактивные. Единственный активный брекпоинт - это брекпоинт на функции WinMain. И это мне тоже кажется странным, т.к. я отключил оптимизацию кода. Или может моё понимание логики работы ATL сильно расходится с тем, как она в действительности работает или должна работать. Я это спрашиваю потому, что хотел бы понять логику этой библиотеки, даже если придётся с ней работать из Visual Studio, хотя жалко конечно терять возможности VCL, которые вполне можно было бы совмещать с возможностями ATL, если бы всё работало так, как надо.

DG>> Так а почему она интерфейс регистрирует, а кокласс, который
DG>> интерфейс(ы) реализует не регит? Можно было бы ручками подправить, но
DG>> я не силён в том, что надо в реестр записывать для COM-объекта, чтобы
DG>> его корректно клиент понимал. И в книгах по COM об этом почти нигде не
DG>> пишется.

VF> MSDN. Там все есть. Разобраться все равно придется, если с COM планируешь
VF> работать.

К сожалению, по самой библиотеке ATL там почти нет информации, а свой велосипед изобретать слишком хлопотно.
Желаю Вам всего наилучшего, Vlad.Дмитрий.

--- Вот такой вот наглый Дед со стажем в 3.0.1-asa9 SR1 лет!
* Origin: Default ORIGIN (FidoNet 2:461/48.125)

Ответы на это письмо:

From: Username
Заголовок следующего сообщения в треде может быть длинным и его придется перенести на новую строку

From: Username
Или коротким

FGHI-url этого письма: area://RU.CBUILDER?msgid=2:461/48.125@FidoNet+4a037796