![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Определение адреса конструктора [D6, Win95/98, WinME, NT4, Win2k, WinXP]
Ученик © (2002-07-16 16:13:00)Можно по адресу класса определить адрес конструктора объектов этого класса ?
var
P : Pointer;
begin
P := TBitmap;
Необходимо вычислить адрес TBitmap.Create, используя P, возможно ли ?
Digitman (2002-07-17 14:32:00) [1]>Ученик
За меня не волнуйся)
Мне совершенно по-барабану беспредметный треп постороннего.
Вот гораздо важнее, что ты скажешь по теме ...
Но ты-таки решил закрыть тему, не доведя ее до истины ... И совершенно напрасно ...
Skier (2002-07-17 13:23:00) [2]Ребята, завязывайте...
Ученик (2002-07-17 13:22:00) [3]>Уролог
Вы сейчас полностью дискредитировали уважаемого Digitman.
Уролог (2002-07-17 13:10:00) [4]Господа ! Сдается мне, старому специалисту, что у Digitman © потолще и подлиннее, чем у Ученик. И есть подспудная мысль, что Ученик"а мучает юношеский максимализм. Но это уже к другому специалисту.
Ученик (2002-07-17 13:04:00) [5]>Digitman
)
Digitman (2002-07-17 13:00:00) [6]>Ученик
Да как тебе будет угодно, сударь)
Ученик (2002-07-17 12:52:00) [7]>Digitman
Без комментариев
Digitman (2002-07-17 12:48:00) [8]>Ученик
Так вот если "сам не знаю что хочу" - разберись для начала, а потом уже упрекай стремящихся помочь тебе в невнимательности. С аргументами серьезными, а не словоблудием !
Ученик (2002-07-17 12:44:00) [9]>Digitman
Если Вам будет легче, то каюсь, я сам не знаю что хочу, задаю дурацкие вопросы и не прислушиваюсь к ответам великих мастеров Delphi, надеюсь мы не будем продолжать, кто-то должен оказаться умнее.
Digitman (2002-07-17 12:40:00) [10]>Ученик
Чушь. В данном случае именно ты невнимателен.
Цитирую тебя :
(1)
>>Необходимо вычислить адрес TBitmap.Create, используя P, >>возможно ли ?
(2)
>>Вызывается конструктор TObject
Вот - еще раз - код, отвечающий на твой вопрос (1) и опровергающий твое утверждение (2)
Тот самый твой TBitmap - не имеющий к TComponent отношения.
procedure TfMain.ButtonXClick(Sender: TObject);
var
var
p: procedure;
c: TClass;
t: TObject;
begin
p:= @TComponent.Create; // вот тебе адрес
RegisterClass(TBitmap);
c:= GetClass("TBitmap");
asm
mov dl,1
mov eax, [c]
call dword ptr [p] // вот тебе создание объекта TBitmap
mov [t], eax
end;
t.free; // вот тебе разрушение созданного объекта TBitmap
end;
Отрассируй и убедись сам !!!
Ученик (2002-07-17 12:03:00) [11]>Digitman
Внимательности, внимательности и еще раз внимательности, прочитайте еще раз эту страницу.
Digitman (2002-07-17 11:56:00) [12]>Ученик
Я вот не вижу, что ты "остановился" ...
Так ты до сих пор и не смог вразумительно объяснить суть проблемы...
Тебе ж сказали уже - в любом случае нужно заранее знать класс зарегистрированного объекта, иметь ссылку на дескриптор класса и иметь декларацию его конструктора . Только тогда с помощью VMT можно вызывать конструирующие методы класса с приведенными выше оговорками.
Ученик (2002-07-17 11:26:00) [13]>Digitman
>И я об этом говорю, только вот он никак это , видимо, не >уразумеет.
Я уже давно остановился Ученик (16.07.02 19:36)
>TComponent - прямой наследник TPersistent, и непонятно в таком >случае, какие у тебя сложности, если ты говоришь, что >конструируешь любого наследника TComponent без проблем.
Внимательности вам не хватает мастера (Digitman, Юрий Зотов), внимательности, а так цены бы вам не было ))), так много и хорошо пишете про простые вещи.
Digitman (2002-07-17 11:16:00) [14]>vuk
>>Автору вопроса в решении его задачи это ни коим образом не поможет
Разумеется, не поможет ! И я об этом говорю, только вот он никак это , видимо, не уразумеет.
А все то, что я , как ты говоришь, "сложно" изложил - лишь в стремлении именно наглядно показать, что адрес корректно определяется и явный вызов констр.метода по полученному адресу вполне возможен, но сопряжен с вышеописанными проблемами.
>Ученик
TComponent - прямой наследник TPersistent, и непонятно в таком случае, какие у тебя сложности, если ты говоришь, что конструируешь любого наследника TComponent без проблем.
vuk (2002-07-17 10:58:00) [15]>Здесь есть вот какие тонкости
Я именно об этом. Вообще говоря, можно написать то, что написали Вы несколько проще. Если вспомнить, что конструктор - функция, возвращающая созданный экземпляр, то все просто. Конструктор без параметров можно представить примерно так:
type
TSimpleConstructor = function (ClassRef : TClass) : TObject; register;
соответственно конструктор TComponent будет иметь вид
type
TComponentConstructor = function (ClassRef : TClass; AOwner : TComponent ) : TObject; register;
Тогда вызов делается проще. Предположим, что в вышем примере переменная p имеет тип TComponentConstructor и содержит адрес конструктора, тогда его вызов будет примерно следующим:
asm
mov dl, 1
end;
t := P(c, nil);
Вот только в приведенном Вами примере все это будет лишним, поскольку все то же самое можно сделать проще, поскольку у наследников TComponent есть виртуальный конструктор и все действия, приведенные выше не особо нужны. Автору вопроса в решении его задачи это ни коим образом не поможет, поскольку он не знает, какого класса экземпляры он будет создавать и следовательно не будет иметь возможности получить адрес конкретного конструктора (у Вас это сделано явно в выделенной строке).
А с наследниками TComponent все просто. Предположим, что в переменной A содержится экземпляр какого-то наследника TComponent, тогда:
C := TComponentClass( A.GetClass ).Create( nil );
Ученик (2002-07-17 10:52:00) [16]>Игорь Шевченко
Речь шла о конструкторе
>Digitman
У нас проблема с вызовом конструкторов объектов порожденных от TObject и TPersistent, с компонентами проблем нет у них конструктор override; и все вызывается обычным образом
TComponentClass(FindClass("Имя класса")).Create(AOwner)
Digitman (2002-07-17 10:32:00) [17]>Ученик
Как это - нет ? Вот же он !
procedure TfMain.ButtonXClick(Sender: TObject);
var
var
p: procedure;
c: TClass;
t: TObject;
begin
p:= @TComponent.Create;
c:= GetClass("TComponent");
asm
mov dl,1 // создавать экземпляр
mov eax, [c] // VMT
mov ecx, 0 // Owner = nil
call dword ptr [p] // собственно - вызов конструктора по адресу
mov [t], eax // результат - ссылка на созданный и иниц-ный экз-р
end;
t.free; // разрушение созданного объекта
end;
Игорь Шевченко (2002-07-17 10:20:00) [18]Адрес деструктора прописан в таблице VMT со смещением -4
(vmtDestroy)
Ученик (2002-07-17 10:10:00) [19]>Digitman
Если что-то надо, можно и на встроенном ассемблере написать, только вот похоже адреса то нету, в любом случае, спасибо.
Digitman (2002-07-17 10:02:00) [20]>vuk
Здесь есть вот какие тонкости :
Если перед вызовом конструирующего метода некоего класса РОН dl = 1, то непосредственно перед инициализацией экземпляра будет вызвана системная процедура ClassCreate, отвечающая за генерацию экземпляра. В противном случае (РОН dl = 0) будет произведена только попытка инициализации, и это приведет к исключению при отсутствии экземпляра.
Все inherited-конструкторы вызываются с dl = 0.
Вызов любого конструирующего метода любого класса всегда предваряется занесением в РОН eax адреса VMT
Кр.того, если конструирующий метод класса имеет параметры, их также нужно передавать : первый параметр (в порядке их перечисления в декларации конструктора) - в РОН ecx, остальные - последовательным занесением в стек.
>Ученик
Всю эту последовательность действий формирует компилятор "прозрачно" для программера.
Незнание этих фактов при явном (по факт.вычисленному адресу) вызове конструктора обязательно приведет к исключительной ситуации.