Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 23.09.2015, 21:58   #1
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,770
По умолчанию Подключиться к разделяемому COM-объекту

Подскажите пожалуйста, как правильно подключаться к разделяемому COM-объекту и как этот объект правильно написать?

Предположим, имеется некий объект, выполняющий роль сервера имен в какой-то среде:
Код:
type
  INameServer = interface ['{6C7A6C13-F789-4E83-A744-FBC39C8F05EB}']
    function GetSharedMemoryName: WideString;
  end;

  TNameServer = class(TComObject, INameServer)
  private
    FName: WideString;
  protected
    function GetName: WideString;
  public
    procedure Initialize; override;
  end;

{ TNameServer }

function TNameServer.GetName: WideString;
begin
  Result := FName;
end;

procedure TNameServer.Initialize;
begin
  FName := 'aa569';
end;

initialization
  TComObjectFactory.Create(ComServer, TNameServer, CLSID_NameServer,
    'NameServer', '', ciSingleInstance, tmSingle);
Нижнюю строчку инициализации создает сам Delphi при генерации скелета COM-объекта. Я не уверен, что она в правильном месте стоит. Всё это происходит в exe-шнике.

Как потом подключиться к этой хрени и получить имя? Имя должно быть одно для нескольких подключающихся клиентов, то есть разделяемое.
Vapaamies вне форума Ответить с цитированием
Старый 23.09.2015, 22:05   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Я наверное сейчас реально затуплю, ибо чет туго вопрос понял, но из того, что понял:
Код:
uses  comobj, 
...
var o:OleVariant;
begin
 o:=CreateOleObject('NameServer');
 Caption:=o.GetName;
end;
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 23.09.2015, 23:31   #3
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,770
По умолчанию

Это для OLE-объекта в библиотеке, а у меня COM-объект (по интерфейсу) в exe-файле.
Vapaamies вне форума Ответить с цитированием
Старый 24.09.2015, 00:09   #4
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

OLE сами по себе COM объекты, просто они заточены под определенные задачи.

Правильно начать с написания IDL файла, который описывает ваш интерфейс.
С его помощью генерится type library, которая регистрируется в системе, как и сам COM клас. Объект регистрируется как out of process server, после этого при попытки создания этого класса через CoCreateInstance ЕХЕ файл запустится. После запуска ЕХЕ регистрирует класс в running table с помощью CoRegisterClassObject.

type library дает возможность движку COM автоматизировать вызовы между процессами. Если нет type library, надо будет самому писать proxy/stub для каждого интерфейса, регистрировать их в системе и т.д.
waleri вне форума Ответить с цитированием
Старый 24.09.2015, 16:37   #5
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,770
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
С его помощью генерится type library, которая регистрируется в системе, как и сам COM клас. Объект регистрируется как out of process server, после этого при попытки создания этого класса через CoCreateInstance ЕХЕ файл запустится.
Сейчас в проекте нет библиотеки типов, но программа-именователь запускается автоматом при вызове из другой через COM (типа как Word или Excel). В реестре записи есть. Полагаю, что Delphi своими обертками делает черновую работу. В коде TComObjectFactory как раз есть методы, отвечающие за обновление реестра. Откуда-то они вызываются, видимо.

Про библиотеку типа понял, попробую поэкспериментировать. Всегда казалось, что это просто разновидность RTTI, ориентированной на COM, чтобы импортирующие программы могли сгенерировать интерфейсы и обвязку, не имея исходников. У меня же исходники есть.

Модели потоков вроде должны в параметрах задаваться, есть выбор между tmApartment, tmSingle, tmNeutral и tmBoth.

Цитата:
Сообщение от waleri Посмотреть сообщение
После запуска ЕХЕ регистрирует класс в running table с помощью CoRegisterClassObject.
Про это читал ночью. Догадываюсь, что в Delphi оберток под это нет, нужно писать вручную. Вчера уже пошел спать, ща как раз продолжу.

Вобщем фигня какая-то. Сделал библиотеку типов, всё прописал.
Код:
[
  uuid(0C2FE7A1-9D43-4CA9-A14D-A2725FCB4485), 
  version(1.0), 
  helpstring("Namer Library")
    
]
library Namer
{

  importlib("stdole2.tlb");

  [
    uuid(BB533887-1DD2-47FC-B88C-39ED1C7FC6A4), 
    version(1.0), 
    helpstring("Интерфейс именователя")
  ]
   interface INameServer: IUnknown
  {
    [
    id(0x00000065)
    ]
    BSTR _stdcall GetName( void );
  };

  [
    uuid(5AFA5B4F-6C1B-4C39-A459-B3978DBCCD41), 
    version(1.0), 
    helpstring("Именователь в виде объекта COM")
  ]
  coclass NameServer
  {
    [default] interface INameServer;
  };

};
Потом пытался сделать по примеру с CodeProject:
Код:
const
  IID_IClassFactory: TGUID = '{00000001-0000-0000-C000-000000000046}';

function GetComObject(const CLSID, IID: System.TGUID): IInterface;
var
  Factory: IClassFactory;
begin
  OleCheck(CoGetClassObject(CLSID, CLSCTX_LOCAL_SERVER, nil, IID_IClassFactory, Factory));
  OleCheck(Factory.CreateInstance(nil, IID, Result));
end;
Вызов этой функции дает ошибку "Интерфейс не зарегистрирован", та же фигня и через дельфевый CreateComObject.

Ну вот, скомпилил пример CodeProject-а в VS, а он выдает "CoGetClassObject(): Error(80040154): Класс не зарегистрирован".

Цензурные слова у меня кончились.

Последний раз редактировалось Stilet; 24.09.2015 в 17:41.
Vapaamies вне форума Ответить с цитированием
Старый 24.09.2015, 21:44   #6
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Объект должен быть зарегистрирован в реестре, либо "вручную" в running table (CoRegisterClassObject). Я, правда, не в курсе что и как делает Дельфи, все что я пишу это с точки зрения самого COM.
waleri вне форума Ответить с цитированием
Старый 24.09.2015, 22:24   #7
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,770
По умолчанию

Реестр я первым делом проверил. В реестре всё есть и в случае Delphi, и в случае Visual Studio. А вот ошибки почти похожи.
Vapaamies вне форума Ответить с цитированием
Старый 24.09.2015, 23:22   #8
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Нет, это весьма разные ошибки.
Class not registered указывает, что объект вообще не зарегистрирован и/или в данных в реестре допущена ошибка.
Interface not registered указывает, что объект найден и его пытаются создать, но для нужного интерфейса нет зарегистриванного proxy/stub DLL. Это DLL будет грузится в оба процесса и должен будет заниматься маршалингом данных для вызовов. Обычно этим занимается сам COM на основе type library.

Как регистрировали sample из CodeProject? В том примере есть reg фйла но его надо допиливать.
waleri вне форума Ответить с цитированием
Старый 25.09.2015, 13:20   #9
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,770
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
Как регистрировали sample из CodeProject? В том примере есть reg фйла но его надо допиливать.
Сначала вообще никак не регистрировал, потому что и Delphi, и VS должны самостоятельно регистрировать разрабатываемый COM-объект. Когда полезли ошибки, попробовал зарегить из командной строки через tregsvr от Borland и от .NET тоже какая-то утилита есть...

Блин, только сейчас заметил, что там есть исходники, которые можно скачать. Вчера в упор не видел ссылку. Копировал исходник из статьи, проделав нужные действия в VS вручную.

Посмотрел этот reg-файл, поискал его GUID в своем реестре, не нашел. Еще один

Отредактировал reg-файл под себя, применил. Теперь при запуске клиента запускается приложение сервера и... клиент зависает при попытке получить интерфейс фабрики классов:
Цитата:
Get the class factory interface for the Car class...CoGetClassObject(): Error(80080005): Ошибка при выполнении приложения-сервера
Vapaamies вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Атомарный доступ к разделяемому ресурсу TELEPUZ C# (си шарп) 2 19.03.2014 11:39
доступ к объекту Unique_Maks Общие вопросы Delphi 4 27.07.2013 20:27
Вопрос по COM объекту koljsch C++ Builder 15 16.09.2012 22:16
вопрос по объекту Comment Обыватель Microsoft Office Excel 4 25.12.2009 10:49
вопрос по объекту tchart prasvit Помощь студентам 6 25.03.2009 21:45