Форум: "Основная";
Текущий архив: 2002.07.29;
Скачать: [xml.tar.bz2];
ВнизОпределение адреса конструктора Найти похожие ветки
← →
Ученик (2002-07-16 16:13) [0]Можно по адресу класса определить адрес конструктора объектов этого класса ?
var
P : Pointer;
begin
P := TBitmap;
Необходимо вычислить адрес TBitmap.Create, используя P, возможно ли ?
← →
Skier (2002-07-16 16:20) [1]>Ученик
Зачем ?
Что хочешь сделать ??
← →
Ученик (2002-07-16 16:23) [2]>Skier
Вызывать по адресу класса создание объектов этого класса, с компонентами все понятно, там constructor; override;, а вот если от TPersistent или TObject ????
← →
Skier (2002-07-16 16:27) [3]>Ученик
для TPersistent копай :
- RegisterClass
- UnRegisterClass
- RegisterClasses
- UnRegisterClasses
- FindClass
- GetClass
← →
Ученик (2002-07-16 16:29) [4]Вызывается конструктор TObject
← →
Skier (2002-07-16 16:30) [5]>Ученик
В догонку :
Почитай про метаклассы.
← →
Skier (2002-07-16 16:32) [6]>Ученик
А почему TObject у тебя же TBitmap ?
← →
Digitman (2002-07-16 16:38) [7]ну, к примеру :
showmessage(inttohex(integer(@ TBitmap.Create), 8));
А если метод-конструктор с интересующим тебя именем объявлен как overload ? Что тогда ?
И - зачем это тебе ? Если не секрет ?
← →
Ученик (2002-07-16 16:41) [8]>Skier
var
P : TPersistentClass;
begin
RegisterClasses([TBitmap]);
P := GetClass("TBitmap");
if P <> nil then
P.Create;
Вызывается TObject.Create
>Digitman
Вызывать по адресу класса создание объектов этого класса.
← →
Digitman (2002-07-16 16:42) [9]Ну, предположим, вызовешь ты конструирующий метод класса ..
А экземпляр-то собственно кто будет за тебя создавать ?
← →
Skier (2002-07-16 16:48) [10]>Ученик
type
TBitmapClass = class of TBitmap;
var
P : TBitmapClass;
begin
RegisterClasses([TBitmap]);
P := TBitmapClass(GetClass("TBitmap"));
if P <> nil then P.Create;
← →
Ученик (2002-07-16 16:53) [11]>Digitman
Экземпляр то создается, и P.Create.Free вызовет TBitmap.Destroy, только вот конструктор вызвать проблема.
← →
Ученик (2002-07-16 16:56) [12]>Digitman
Экземпляр то создается, и P.Create.Free вызовет TBitmap.Destroy, только вот конструктор вызвать проблема.
>Skier
TBitmap взят для примера, на его месте может быть любой другой.
Есть какая-то таблица методов, конструкторы там не постоянном месте ?
← →
Digitman (2002-07-16 17:39) [13]>Ученик
Нет, подожди ...
кем/чем и как будет создаваться экземпляр у тебя, коль ты не хочешь отказаться от услуг компилятора ?
тело метода-конструктора этим не занимается, его задача - инициализация уже существующего экземпляра
← →
Ученик (2002-07-16 17:46) [14]>Digitman
Я не знаю ответа, я еще только учусь, просто попробуйте выполнить код который указан выше, объекты создаются,
не вызывается конструктор определенный именно для них
← →
Skier (2002-07-16 17:55) [15]>Ученик
К сожалению, у потомков TPersistent конструктор не
перекроешь (override).
Это можно делать только начиная с TComponent :(
← →
Digitman (2002-07-16 17:56) [16]>Ученик
Конечно , объект будет создаваться в этом примере ! В этом и сомнений нет )
Но ведь в этом примере работу по внедрению и вызову кода создания экземпляра неявно выполняет за тебя компилятор ...
Ты же хочешь вызвать некий метод-конструктор в run-time просто как некую процедуру инициализации экземпляра. Вопрос - какого экземпляра ? Об этом придется заботиться самостоятельно ...
Еще один вопрос - а как ты надеешься вызывать метод-конструктор, даже зная его адрес, если он имеет один или более (заранее неизвестно) параметров ?
← →
Ученик (2002-07-16 18:16) [17]>Digitman
>Ты же хочешь вызвать некий метод-конструктор в run-time просто >как некую процедуру инициализации экземпляра.
Я хочу вызвать конструктор объекта, по-моему он должен делать все, по-крайней мере кроме вызова TObject.Create там больше ничего нет. С несколькими параметрами действительно беда, но на это хотелось пока закрыть глаза, хотя какие-то странные сообщения мелькают в Delphi, если библиотеки компонентов не соответствуют друг другу.
← →
Юрий Зотов (2002-07-16 18:25) [18]> Ученик
Что-то все у Вас запутано как-то. Объясните просто - что нужно сделать? Создать некомпонентский объект, зная ссылку на его класс? Или что-то другое?
А Ваш пример
type
TBitmapClass = class of TBitmap;
var
P : TBitmapClass;
begin
RegisterClasses([TBitmap]);
P := TBitmapClass(GetClass("TBitmap"));
if P <> nil then P.Create;
полностью эквивалентен самому обычному вызову TBitmap.Create. Зачем такие навороты?
← →
Ученик (2002-07-16 18:29) [19]>Юрий Зотов
Вы чего-то напутали, это не мое.
← →
Skier (2002-07-16 18:31) [20]Это моё. Просто я-то думал что Ученик хочет иметь
дело с наследниками TBitmap-а.
Он что-то другое задумал:)
← →
[NIKEL] (2002-07-16 18:36) [21]по моему адреса деструктора и конструктора получить невозможно...
← →
Skier (2002-07-16 18:39) [22]>[NIKEL]
showmessage(inttohex(integer(@TBitmap.Create), 8));
Чем тебе не адрес ? :)
← →
Юрий Зотов (2002-07-16 18:48) [23]Действительно напутал, приношу свои извинения.
Н в чем же, все-таки вопрос? Понимаете, я не зря спрашиваю. Я уточняю потому, что примерно догадываюсь, что Вы хотите и знаю, как это делается. Но чтобы говорить, нужно не догадываться, а быть полностью уверенным.
← →
Ученик (2002-07-16 19:11) [24]>Юрий Зотов
Так тут нет никаких подводный камней, хочется по адресу класса создать объект этого класса.
← →
vuk (2002-07-16 19:18) [25]to Digitman:
>тело метода-конструктора этим не занимается, его задача -
>инициализация уже существующего экземпляра
....
>Ты же хочешь вызвать некий метод-конструктор в run-time просто
>как некую процедуру инициализации экземпляра. Вопрос - какого
>экземпляра ? Об этом придется заботиться самостоятельно ...
Здесь Вы не правы. Созданием экземпляра занимается именно конструктор. И получить его адрес можно, и вызвать тоже можно (если знать как). Только вот единственное - лучше этого не делать. :o)
← →
vuk (2002-07-16 19:25) [26]to Ученик:
Экземпляр создать можно, но не всегда можно это сделать корректно. Например для наследников TComponent это делается просто (там имеется виртуальный конструктор), а вот для других классов это может быть проблематичным.
← →
Ученик (2002-07-16 19:27) [27]>vuk
С другими как раз и вопрос )))
← →
vuk (2002-07-16 19:32) [28]Если Вам нужно создавать экземпляр _любого_ класса, то такая задача в общем виде не решается, поскольку у каждого класса свой конструктор и он ни в каких таблицах не прописан.
← →
Ученик (2002-07-16 19:36) [29]>vuk
>...ни в каких таблицах не прописан.
жаль
← →
Digitman (2002-07-17 10:02) [30]>vuk
Здесь есть вот какие тонкости :
Если перед вызовом конструирующего метода некоего класса РОН dl = 1, то непосредственно перед инициализацией экземпляра будет вызвана системная процедура ClassCreate, отвечающая за генерацию экземпляра. В противном случае (РОН dl = 0) будет произведена только попытка инициализации, и это приведет к исключению при отсутствии экземпляра.
Все inherited-конструкторы вызываются с dl = 0.
Вызов любого конструирующего метода любого класса всегда предваряется занесением в РОН eax адреса VMT
Кр.того, если конструирующий метод класса имеет параметры, их также нужно передавать : первый параметр (в порядке их перечисления в декларации конструктора) - в РОН ecx, остальные - последовательным занесением в стек.
>Ученик
Всю эту последовательность действий формирует компилятор "прозрачно" для программера.
Незнание этих фактов при явном (по факт.вычисленному адресу) вызове конструктора обязательно приведет к исключительной ситуации.
← →
Ученик (2002-07-17 10:10) [31]>Digitman
Если что-то надо, можно и на встроенном ассемблере написать, только вот похоже адреса то нету, в любом случае, спасибо.
← →
Игорь Шевченко (2002-07-17 10:20) [32]Адрес деструктора прописан в таблице VMT со смещением -4
(vmtDestroy)
← →
Digitman (2002-07-17 10:32) [33]>Ученик
Как это - нет ? Вот же он !
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:52) [34]>Игорь Шевченко
Речь шла о конструкторе
>Digitman
У нас проблема с вызовом конструкторов объектов порожденных от TObject и TPersistent, с компонентами проблем нет у них конструктор override; и все вызывается обычным образом
TComponentClass(FindClass("Имя класса")).Create(AOwner)
← →
vuk (2002-07-17 10:58) [35]>Здесь есть вот какие тонкости
Я именно об этом. Вообще говоря, можно написать то, что написали Вы несколько проще. Если вспомнить, что конструктор - функция, возвращающая созданный экземпляр, то все просто. Конструктор без параметров можно представить примерно так:
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 );
← →
Digitman (2002-07-17 11:16) [36]>vuk
>>Автору вопроса в решении его задачи это ни коим образом не поможет
Разумеется, не поможет ! И я об этом говорю, только вот он никак это , видимо, не уразумеет.
А все то, что я , как ты говоришь, "сложно" изложил - лишь в стремлении именно наглядно показать, что адрес корректно определяется и явный вызов констр.метода по полученному адресу вполне возможен, но сопряжен с вышеописанными проблемами.
>Ученик
TComponent - прямой наследник TPersistent, и непонятно в таком случае, какие у тебя сложности, если ты говоришь, что конструируешь любого наследника TComponent без проблем.
← →
Ученик (2002-07-17 11:26) [37]>Digitman
>И я об этом говорю, только вот он никак это , видимо, не >уразумеет.
Я уже давно остановился Ученик (16.07.02 19:36)
>TComponent - прямой наследник TPersistent, и непонятно в таком >случае, какие у тебя сложности, если ты говоришь, что >конструируешь любого наследника TComponent без проблем.
Внимательности вам не хватает мастера (Digitman, Юрий Зотов), внимательности, а так цены бы вам не было ))), так много и хорошо пишете про простые вещи.
← →
Digitman (2002-07-17 11:56) [38]>Ученик
Я вот не вижу, что ты "остановился" ...
Так ты до сих пор и не смог вразумительно объяснить суть проблемы...
Тебе ж сказали уже - в любом случае нужно заранее знать класс зарегистрированного объекта, иметь ссылку на дескриптор класса и иметь декларацию его конструктора . Только тогда с помощью VMT можно вызывать конструирующие методы класса с приведенными выше оговорками.
← →
Ученик (2002-07-17 12:03) [39]>Digitman
Внимательности, внимательности и еще раз внимательности, прочитайте еще раз эту страницу.
← →
Digitman (2002-07-17 12:40) [40]>Ученик
Чушь. В данном случае именно ты невнимателен.
Цитирую тебя :
(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;
Отрассируй и убедись сам !!!
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2002.07.29;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.007 c