Форум: "Основная";
Текущий архив: 2005.08.21;
Скачать: [xml.tar.bz2];
ВнизПроблема с видимостью полей объекта Найти похожие ветки
← →
sunsay © (2005-07-28 13:27) [0]Привет всем мастерам!
Кто-нить сталкивался со следующей проблемой?
Только сейчас (точнее, уже дня три "танцы с бубном") наткнулся в своём проекте, раньше не замечал...
При работе метода объекта почему-то не видно полей (переменных) этого объекта и приложение вылетает при попытке доступа к любому полю.
Сейчас попробую объяснить подробнее:
В начале работы моей программы некоторые объекты "регистрируют" свои обработчики в менеджере сообщений на какие сообщения они будут реагировать, допустим:
type
TMailSender = class (TBaseClass)
//...
FSomeVariable: String;
procedure SomeMethod;
procedure OnSendMail(var Msg: TCustomMessage);
//...
end;
constructor TMailSender.Create(aLogFileName: String);
begin
FLogFileName := aLogFileName;
MessageManager.RegisterMessageHandler("mm_send_mail", OnSendMail);
end;
в классе менеджера сообщений (TMessageManager), описание этой процедуры (RegisterMessageHandler) выглядит так:
вообщем эта процедура определенным образом сохраняет указатель обработчика @Handler:
type TMessageHandler = procedure (var Msg: TCustomMessage) of object;
function TMessageManager.RegisterMessageHandler(MessageName: String; Handler: TMessageHandler): Boolean;
var P: Pointer;
...
P := @Handler;
Потом во время работы программы, какай-то объект создал сообщение и вызывает MessageHandler.DispatchMessage, в параметре передает сообщение.
в DispatchMessage смотрим какое имя у сообщение Msg.Name, ищем какие обработчики были на это имя зарегистрированны
и запускаем один обработчик вот так:
procedure TMessageManager.DispatchMessage(var Msg: TCustomMessage);
var Handler: TMessageHandler;
...
@Handler := P;
Handler(Msg);
Обработчик запускается замечательно - все локальные переменные работают, методы объекта вызываются, но при попытке получить доступ к полям обекта - вылетает программа с 216 ошибкой.
procedure TMailSender.OnSendMail(var Msg: TCustomMessage);
begin
Self.SomeMethod; // работает замечательно
FSomeVariable := "sdsdsd"; // ! ошибка - почему то в отладчике в watches написано inaccessible value
end;
Если кто-то досюда дочитал, уже спасибо :) А если ещё и понял что-нибудь, то тогда поделитесь мыслями или задайте наводящие вопросы, если что, могу код переслать.
Медленно но верно начинаю нервничать, у меня дергается правый глаз и уходит две пачки сигарет в день :)))
Одна просьба, не спрашивать меня зачем я так делаю (в смысле общения объектов через сообщения) - долго объяснять...
← →
Digitman © (2005-07-28 13:46) [1]
> Self.SomeMethod
зачем Self ? в данном контексте компилятор и так поймет, что речь идет о текущем экземпляре - ты ведь в теле этого метода к иным экз-рам данного класса не обращаешься, только к текущему
> ошибка - почему то в отладчике в watches написано inaccessible
> value
т.е. то что "в watches написано" и есть по-твоему не иначе как ошибка ?
← →
Leonid Troyanovsky © (2005-07-28 13:48) [2]
> sunsay © (28.07.05 13:27)
> var P: Pointer;
> ...
> P := @Handler;
Какое такое P? Да еще и Pointer.
Ведь regular procedure vs method of class - две большие
разницы. Используй уж лучше поля для ссылок на методы,
на манер TNotifyEvent.
--
Regards, LVT.
← →
evvcom © (2005-07-28 13:48) [3]
> Self.SomeMethod;
Достаточно просто SomeMethod;
Очень похоже на то, что объекта уже нет. А что в Watch показывает Self и Pointer(Self)?
← →
evvcom © (2005-07-28 13:52) [4]Да, кстати, точно. См. [2], ты теряешь Self в P := @Handler;
← →
sunsay © (2005-07-28 16:46) [5]Ну Self там действительно необязательно - так, написал, взгрустнулось наверное, не в этом фишка...
TO evvcom> объект есть, это сто пудово - его никто не освобождает...
TO Leonid Troyanovsky> то есть если я просто запоминаю указатель на метод объекта, а потом пытаюсь вызвать её - такое не пройдет и я типа теряю связь с самим объектом?
← →
Leonid Troyanovsky © (2005-07-28 16:56) [6]
> TO Leonid Troyanovsky> то есть если я просто запоминаю указатель
> на метод объекта, а потом пытаюсь вызвать её - такое не
> пройдет и я типа теряю связь с самим объектом?
Да.
Размер TMethod - 8, а Pointer -4.
Т.е., указатель на объект теряется.
--
Regards, LVT.
← →
sunsay © (2005-07-28 17:03) [7]
> Размер TMethod - 8, а Pointer -4.
> Т.е., указатель на объект теряется.
Странно всё это, вот тут написал простенькую программку, почему то в ней всё работает... уже запутался окончательно, придется копать в коде скорее всего.
uses windows;
type
// вот наш класс
TSampleObject = class
public
Variable: String;
procedure Method;
end;
// вот наш метод
procedure TSampleObject.Method;
begin
Variable := "Sample";
MessageBox(0, PChar(Variable), nil, MB_OK);
end;
type
TMethod = procedure of object;
var
Method: TMethod;
SampleObject: TSampleObject;
P: Pointer;
begin
SampleObject := TSampleObject.Create; // создаем объект
Method := SampleObject.Method; // вот наш метод
P := @Method; // запоминаем адрес метода
@Method := nil; // указатель на метод обнуляем, то есть если
// если попробуем вызвать сейчас Method - всё нафиг вылетит
@Method := P; // возвращаем на место (из Pointer"а, кстати, который 4 байта)
Method; // всё чудесно работает, и к Variable я почему-то имею доступ
SampleObject.Free; // освобождаем объект
end.
← →
han_malign © (2005-07-28 17:19) [8]>возвращаем на место (из Pointer"а, кстати, который 4 байта)
- nil, кстати, тоже 4 байта - второе поле структуры Method(где лежит тот самый указатель на экземпляр) не обнуляется...
System.pas:
TMethod = record
Code, Data: Pointer;
end;
Так что - без всяких "почему-то"...
← →
han_malign © (2005-07-28 17:21) [9]короче, поменяй Pointer на TMessageHandler - и будет тебе щастье...
← →
sunsay © (2005-07-28 17:24) [10]
> короче, поменяй Pointer на TMessageHandler - и будет тебе
> щастье...
круто... пойду проверять.
← →
sunsay © (2005-07-28 17:38) [11]Пасиб всем огромный! Разобрался.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2005.08.21;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.053 c