Текущий архив: 2005.06.06;
Скачать: CL | DM;
Вниз
Создание COM сервера Найти похожие ветки
← →
Vitalik © (2004-08-26 10:27) [0]Привет! Я пытаюст создать COM сервер в виде файла EXE. Помогите пжалста, оцените ход моих мыслей, что для этого нужно сделать!
Я бы не хотел пользоваться мастерами, потому что так не интересно и ничего не понятно ;)
Для этого делаю следующее:
0. создаю новый проект в Delphi, удаляю все модули с формами, application.initialization, application.run - к чертям.
Оставляем:
programm cnsCalc
begin
end.
Это и будет моей отправной точкой :)
1. Создаю (в новых отдельных модулях) несколько своих интерфейсов и реализующих их классов - не важно какие это COM объекты,
главное, что они будут содержаться в моём сервере.
2. Для того, чтобы COM сервер был COM сервером, нужно чтобы в нём была хотя бы одна фабрика классов (используя которую, можно будет найти любой интерфейс в сервере)
Фабрика классов (на сколько я понимаю) - это класс, реализующий интерфейс IClassFactory. Это вообще правильно?
Я выполнил этот класс просто:
TFactory = class(TInterfacedObject, IClassFactory)
private
FServLocks: integer;
protected
function _Release: Integer; stdcall;
public
constructor Create;
function CreateInstance(const unkOuter: IUnknown; const iid: TIID;
out obj): HResult; stdcall;
function LockServer(fLock: BOOL): HResult; stdcall;
end;
constructor TFactory.Create;
begin
FServLocks := 0;
end;
Ну методы _Release и LockServer я выполняю так:
function TFactory.LockServer(fLock: BOOL): HResult;
begin
If FLock then
FServLocks := InterlockedIncrement(FServLocks)
else
FServLocks := Interlockeddecrement(FServLocks)
end;
//Т.е. получается, клиентские приложения могут блокировать фабрику в памяти, чтобы она не выгружалась, пока все блокировки будут сняты? (код для этого метода я не сам придумал - у сишников дюзнул :)
function TFactory._Release: Integer; stdcall;
begin
Result := InterlockedDecrement(FRefCount);
if (FServLocks = 0) and (Result = 0) then
Destroy;
end;
Ну и самое интересное - реализация метода CreateInstance, который, в моём понимании, получает от клиентской программы интерфейс, и если этот интерфейс реализуется на сервере, то нужно создать реализующий объект и вернуть ссылку на интерфейс. Для простоты я выполнил этот метод так:
function TFactory.CreateInstance(const unkOuter: IInterface;
const iid: TIID; out obj): HResult;
var
IC : ICalc; //в одном из модулей моего проекта описан интерфейс ICalc. ICalc = interface...
Calc : TCalc; //...который реализуется классом TCalc. TCalc = class(TInterfacedObject, ICalc)
begin
If IsEqualIID(iid, CLSID_Calc) then //CLSID - если это IID интерфейса ICalc
begin
Calc := TCalc.Create; //создаём реализующий объект в памяти...
IC := Calc;
result := IC.QueryInterface(iid, obj); //Так как в предке TCalc (TInterfacedObject) метод QueryInterface находится в секции protected, то обращаемся к этому методу через интерфейс...
end;
end;
Ну вот вроде и всё пока... Возвращением соответствующего результата в остальных случаях (когда, например, передан неверный iid) пока голову не забиваем...
3. Теперь мне нужно сделать так, чтобы при запуске COM сервера моя фабрика классов регистрировалась в системе и клиентские программы могли получать на неё интерфейс.
Как это сделать?
Предполагаю, что нужно в точке входа в программу (begin ... end.) использовать функцию CoCreateInstance, или CoGetClassObject...
Но как ими правильно пользоваться? Тут для меня вообще начался тёмный лес :(
описана функция так:
STDAPI CoCreateInstance(
REFCLSID rclsid, //Class identifier - идентификатор класса?!?! Что это? Какого класса?
LPUNKNOWN pUnkOuter, //Object is or isn"t part of an aggregate - а это что? Ну мы это пока не проходили, вроде как можно покаместь nil использовать :) Хотя, всё равно интересно :)
DWORD dwClsContext, //Context for running executable code - это, насколько я понимаю, определяет в каком процессе будут работать COM объекты сервера - в процессе клиента, в другом процессе, в процессе другой машины и т.п.
REFIID riid, //Interface identifier - это, как я понимаю, как раз идентификатор (IID) необходимого мне интерфейса... (например, интерфейса iCalc)
LPVOID * ppv //Pointer to storage of interface pointer - а это указатель на интерфейс компонента, который мне нужен и который я получу, если павильно задам riid :)
);
Вот.... Ну как? много я тут дров наломал? :) Насколько верно мое понимания создания COM серверов в файле EXE?
Этож блин, основа, тут нужно всё хорошо понимать! А пока сам не сделаешь...
Вот!
Так как, всё же, зарегистрировать фабрику классов при запуске сервера и как сделать так, чтобы клиентские программы могли использовать мою фабрику классов чтобы использовать COM объекты в моём COM сервере? :)
Спасибо!
← →
Vitalik © (2004-08-26 13:07) [1]Мдя... как мой вопрос оказался похож на
http://www.vserg.ru/doc/articles/combegin.html
:)
Кстати, статья классная, мне очень понравилась!
← →
Vitalik © (2004-08-27 13:18) [2]Упростим вопрос :)
В DLL для создания объекта фабрики классов используется экспортируемая функция DllGetClassObject.
А как создаётся этот COM - объект в случае, если COM сервер реализован в виде исполняемого файла?
← →
Aleksey Pavlov © (2004-08-29 16:16) [3]Сначала читаем "Основы COM" хотя бы до частичного просветления, потом идём сюда с вопросами =)))
По вопросу: любой (внешний(Local) или внутренний (in-proc)) сервер создаётся так или иначе с помощью фабрики классов данного класса COM-сервера. Откуда фабрика классов "знает" как создать сервер и как реализована DllGetClassObject написанно всё в той же книге.
P.S. а изучение COM лучше всё же начинать не с приведённой ссылки ;)
← →
Vitalik © (2004-08-30 06:35) [4]да где их взять-то "основы COM" эти? :(
Ну я вот читал Тенцера "Delphi и технология COM" но этот вопрос я не получил ответа :(
Там (по факту), как и везде - "пользуйтесь, ребята, мастерами"...
а больше книжек в продаже и нету на сегодня!
← →
Vitalik © (2004-08-30 06:37) [5]да где их взять-то "основы COM" эти? :(
Ну я вот читал Тенцера "Delphi и технология COM" но на этот вопрос я не получил ответа :(
Там (по факту), как и везде - "пользуйтесь, ребята, мастерами"...
а больше книжек в продаже и нету на сегодня!
← →
Aleksey Pavlov © (2004-08-30 10:57) [6]Dale Rogerson "Inside COM" Microsoft Press
В русском варианте:
Роджерсон "Основы COM".
http://www.books.ru/shop/books/4668?partner=findbook
Стоит совсем недорого.
А вообще есть такая классная штука, как www.findbook.ru =)
← →
Vitalik © (2004-08-30 12:59) [7]О! Спасибо, Алексей Павлов!
Куплю обязательно, стоит и правда недорого :)
Одно настораживает... "товар закончился у основного поставщика" :) ну ничего, будем надеяться :)
Страницы: 1 вся ветка
Текущий архив: 2005.06.06;
Скачать: CL | DM;
Память: 0.5 MB
Время: 0.043 c