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

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

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 17.12.2012, 11:12   #1
Sibedir
Тот ещё
Старожил
 
Аватар для Sibedir
 
Регистрация: 14.11.2007
Сообщений: 2,281
По умолчанию COM-серверы, Type Library и приведение типов

Работал с com-объектами постаринке, через OleVariant. Вздумалось использовать библиотеку типов. Ну там всё понятно, вопрос из другой оперы. Начнем с кода:
Код:
var
  _Appl: IIcadApplication;

function GetOleObject (ClassName: String): IInterface;
begin
  try
    //Попытка подключиться к уже запущенному экземпляру
    Result := GetActiveOleObject(ClassName);
  except
    try
      //Попытка запустить и подключиться
      Result := CreateOleObject(ClassName);
    except
      MessageDlg ('Не удалось подключиться к "'+ClassName+'".' ,mtError, [mbOK], 0);
      Exit;
    end;
  end;
end;

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  ii: IInterface;
begin
  ii := GetOleObject (Edit1.Text);
  _Appl := ii as IIcadApplication;
  _Appl.Visible := True;
end;
Ага работает. Вот и успокойся, чё те надо еще-та.
А вот так
Код:
...
  _Appl := IIcadApplication(ii);
...
не работает. Ошибка на этапе выполнения. Ну ты ваще... Те чё надо? Верни как было и не взрывай людям мозг

"Объясните мама с папой что к чему"
AS, насколько я понимаю, занимается проверкой а потом уже приведением типа. Но если это сработало первые 100000 раз с as и мы больше ни чего не меняем, то можно не парится с проверками. Ан нет. Прямое приведение приводит к тому, что "Интерфейс не поддерживается"

Вот кстати, нашел вот это
Цитата:
В Win32 это преобразование не будет работать, потому что оно говорит компилятору трактовать ссылку на интерфейс, как если бы это уже была ссылка на интерфейс другого типа. Обычно это преобразование не имеет ценности в Win32.
вот здесь
http://www.transl-gunsmoker.ru/2010/...g-post_12.html
Но всеравно не понял

Последний раз редактировалось Sibedir; 17.12.2012 в 11:31.
Sibedir вне форума Ответить с цитированием
Старый 17.12.2012, 11:31   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 19,042
По умолчанию

А вот что GunSmoker в своем блоге пишет
http://www.transl-gunsmoker.ru/2010/...g-post_12.html
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 17.12.2012, 11:46   #3
Sibedir
Тот ещё
Старожил
 
Аватар для Sibedir
 
Регистрация: 14.11.2007
Сообщений: 2,281
По умолчанию

Уже сморел (см. выше), но не понял
Sibedir вне форума Ответить с цитированием
Старый 17.12.2012, 12:08   #4
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

ii as IIcadApplication = ii.QueryInterface
IIcadApplication(ii) = ничего не делает, пустая операция

F1 QueryInterface, F1 Supports
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 17.12.2012, 21:29   #5
Sibedir
Тот ещё
Старожил
 
Аватар для Sibedir
 
Регистрация: 14.11.2007
Сообщений: 2,281
По умолчанию

Ну наконец-то что-то стало прояснятся. Дома есть возможность поработать в RAD Studio. Там по F7 на строке
Код:
  _Appl := IIcadApplication (ii);
нырнул в модуль System (да, удобно оказалось. В Lazaruse было лень в ассемблер нырять)
Меня обманула собственная логика. Я то думал, что если приведение типов жесткое, то оно жесткое, а оказалось для интерфейсов при "жесткое" приведении типов за дело берется
Код:
procedure _IntfCopy(var Dest: IInterface; const Source: IInterface);
Тогда то я и понял, что если
Код:
var
  ii: IDispatch;
то в _Appl скопируется всё, что относится к IDispatch, а всё добро его прямого потомка
Код:
  IIcadApplication = interface(IDispatch)
останется при ii.
Но оказывается, что если
Код:
var
  _Appl: IIcadApplicationDisp;
(есть там оказывается и такой
Код:
  IIcadApplicationDisp = dispinterface
), то
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
  ii: IDispatch;
begin
  ii := GetOleObject (Edit1.Text);
  _Appl := IIcadApplicationDisp (ii);
  _Appl.Visible := True;
end;
РАБОТАЕТ

Ну вроде разобрался немного. Но ведь ты же, дурилка картонная, всеравно понимаешь, что надо через as приводить. Какого лешего тогда ты тут димагогию разводишь?

Цитата:
Сообщение от GunSmoker
F1 Supports
GunSmoker, уважаемый, поясни пожалуйста.

спустя пару часов -----------------------------------------
или я опять чёт напутал?

Последний раз редактировалось Sibedir; 17.12.2012 в 22:20.
Sibedir вне форума Ответить с цитированием
Старый 18.12.2012, 00:42   #6
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Всё правильно понял.
1. IIcadApplication(ii) - это простое копирование. Соответственно, если в ii лежит что-то совместимое с IIcadApplication - это будет работать, не лежит - не будет.
2. as и Supports - это оболочки к QueryInterface. Они явно запрашивают нужную форму.

Я только не пойму, зачем ты рвёшься делать IIcadApplication(ii). Жёсткое приведение типа - это большое "НЕТ" для работы с интерфейсами.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 18.12.2012, 01:24   #7
Sibedir
Тот ещё
Старожил
 
Аватар для Sibedir
 
Регистрация: 14.11.2007
Сообщений: 2,281
По умолчанию

Цитата:
1. IIcadApplication(ii) - это простое копирование. Соответственно, если в ii лежит что-то совместимое с IIcadApplication - это будет работать, не лежит - не будет.
Во я и не могу понять, какое еще копироваие при приведении типов. Ведь по сути своей ii и _Appl - переменные, в которых хранятся указатели (вот тут я стал очень сильно сомниваться за последние пару часов). Как по мне, так нужно так было:
пишем
Код:
  _Appl := IIcadApplication(id);
а выполняется следующее:
Если _Appl = id то выход
иначе
_Appl := id
IIcadApplication._AddRef
и всё

Но не всё так просто. Вот так вот тоже как-то не работает
Код:
Pointer(_Appl) := Pointer(id);
автар, убей себя абстену
а с объектами работало

Цитата:
Я только не пойму, зачем ты рвёшься делать IIcadApplication(ii). Жёсткое приведение типа - это большое "НЕТ" для работы с интерфейсами.
Использую я конечно as, а вопрос в образовательных целях. С детства так приучили (не знаю, может зря): хочешь ездить на машине - разберись как она устроена, не хочешь разбираться - дальше ларька не ездий.

Последний раз редактировалось Sibedir; 18.12.2012 в 01:32.
Sibedir вне форума Ответить с цитированием
Старый 18.12.2012, 01:46   #8
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Цитата:
Во я и не могу понять, какое еще копироваие при приведении типов
Твой
Код:
var
  _Appl: IIcadApplication;
  ii: IInterface;
begin
  _Appl := IIcadApplication(ii);
end;
эквивалентен:
Код:
var
  _Appl: Integer;
  ii: Single;
begin
  _Appl := Integer(ii);
end;
Это - жёсткое приведение типа. Ты говоришь компилятору "я знаю, что там лежит не то, но ты уж сделай так, как я говорю, верь мне". И компилятор послушно это делает - отбрасывает информацию о типе и выполняет простое копирование.

Это будет работать только тогда, когда типы ii и _Appl действительно двоично совместимы, несмотря на формально разные типы. Само собой, "это работает" - этого ещё не означает. Работать может благодаря случайности. К примеру, в том же примере выше, Integer в себя примет Single и эта операция иногда даже может выдавать ожидаемый результат (скажем, для нуля). Но этого не достаточно, чтобы заключить, что Integer в памяти представляется так же, как Single.

У Delphi есть исключения к правилам жёсткого преобразования типов (например, строки), но интерфейсы сюда не входят.

Цитата:
иначе
_Appl := id
IIcadApplication._AddRef
ээээ.... почему вдруг _AddRef? Если интерфейс не того типа, то нужный можно получить только через QueryInterface.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 18.12.2012, 06:23   #9
Sibedir
Тот ещё
Старожил
 
Аватар для Sibedir
 
Регистрация: 14.11.2007
Сообщений: 2,281
По умолчанию

Цитата:
эквивалентен:
Код:

var
_Appl: Integer;
ii: Single;
begin
_Appl := Integer(ii);
end;
Тоесть это все-таки именно так, как я себе это и представлял. Но почему тогда это работает с IIcadApplicationDisp = dispinterface. Прикол в том, что IIcadApplicationDisp и IIcadApplication имеют один и тот че GUID. В реестре с именем класса 'ZwCAD.Application' (а именно с ним я работаю) связан GUID = '{2ED0A211-E1AD-4152-AA9C-B376FAE8FF95}'. В объектной моделе имеется
Код:
const
...
  CLASS_ZwcadApplication: TGUID = '{2ED0A211-E1AD-4152-AA9C-B376FAE8FF95}';
...
и класс CoZwcadApplication, в котором
Код:
class function CoZwcadApplication.Create: IIcadApplication;
begin
  Result := CreateComObject(CLASS_ZwcadApplication) as IIcadApplication;
end;
Тогда, исходя из всего выше сказанного, получается как-то так:
При подключении к COM-серверу по имени система обращается к CoZwcadApplication.Create. Ведь как становится понятно из http://www.rsdn.ru/article/com/comvs.xml
Цитата:
CoClass – это класс, поддерживающий набор методов и свойств (один или более), с помощью которых можно взаимодействовать с объектами этого класса. Такой набор методов и свойств называется интерфейсом (Interface).
и коментариев в файле объектной модели
Цитата:
// *********************************** **********************************//
// The Class CoZwcadApplication provides a Create and CreateRemote method to
// create instances of the default interface IIcadApplication exposed by
// the CoClass ZwcadApplication. The functions are intended to be used by
// clients wishing to automate the CoClass objects exposed by the
// server of this typelibrary.
// *********************************** **********************************//
CoZwcadApplication = class
...
CoZwcadApplication - и есть тот самый класс для получения нужного интерфейса.
Возвращает CoZwcadApplication.Create ссылку на IIcadApplicationDisp = dispinterface. Именно IIcadApplicationDisp, а не IIcadApplication (именно поэтому трюки с жестким приведением типов и IcadApplicationDisp дают положительный результат). Ведь dispinterface - ключевое звено в технологии Ole(-апп) (я так понял его для того и ввели, чтобы разработчики могли спокойно спать ночью после внесения изменений в ОМ в новой версии своего проекта, он сам с помошью Invoke найдет по индексу переехавшие методы) (такой своеобразный интерфейс интерфейсов). Но обернут он в IIcadApplication = interface(IDispatch)
Код:
class function CoZwcadApplication.Create: IIcadApplication;
begin
  Result := CreateComObject(CLASS_ZwcadApplication) as IIcadApplication;
end;
для удобства работы с ОМ. А то, что у них общий GUID, какбэ намекает нам, что это одно и то же.

Теперь было бы неплохо, если бы всё это оказалось правдой
Пожалуйста, пожалуйста, пожалуйста, скажите ему кто-нибудь что все это правда, иначе я его застрелю

P.S.: Кстати, давно уже надо было выложить
XCAD_TLB.zip

P.P.S.: Кстати, IIcad - это потому, что
Безымянный.JPG
а так-то вообще
Код:
type
...
  ZwcadApplication = IIcadApplication;
...

Последний раз редактировалось Sibedir; 18.12.2012 в 06:32.
Sibedir вне форума Ответить с цитированием
Старый 18.12.2012, 07:33   #10
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Цитата:
Но почему тогда это работает с IIcadApplicationDisp = dispinterface
Видимо потому, что именно его возвращает GetOleObject?
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Ответ


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

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
приведение типов??? nikozavr C# (си шарп) 1 14.05.2011 22:29
NetUserAdd() приведение типов disaer Общие вопросы C/C++ 2 12.05.2011 08:09
С - приведение типов onewho Общие вопросы C/C++ 3 21.11.2010 00:12
View|Type Library _-Re@l-_ Общие вопросы Delphi 0 31.07.2010 15:54
Приведение типов в Qt mike_tihomirov Qt и кроссплатформенное программирование С/С++ 1 19.06.2010 13:14