Подскажите синтаксис

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Подскажите синтаксис

Сообщение Alex333 » 28.11.2011 08:17:52

Есть некая функция, в которую передается указатель на метод (ну, скажем, протоколирование результатов), описанный примерно так:
Код: Выделить всё
TProt = procedure (const sProt:String) of object;

Сам метод выглядит примерно как - то так:
Код: Выделить всё
procedure TFMyForm.Prot(const s:String);
begin
  MyProt.Lines.Add(s);
end;

Функция (из формы) вызывается примерно так:
Код: Выделить всё
MyFunc(@Prot);

Ну а в самой функции что-то такое:
Код: Выделить всё
function MyFunc(FMyProt:TProt):Boolean;
begin
.........
   if Assigned(FMyProt) then
       FMyProt('Что-то-там...');
.........
end;

Вопрос: а как мне подсунуть этой функции (не изменяя её саму) в качестве параметра не указатель на метод формы, а указатель на обычную процедуру, не являющуюся методом? Возможно такое? И как должна быть описана такая процедура?
Alex333
новенький
 
Сообщения: 32
Зарегистрирован: 21.08.2011 19:14:28

Re: Подскажите синтаксис

Сообщение Mr.Smart » 28.11.2011 09:32:53

Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: Подскажите синтаксис

Сообщение Alex333 » 28.11.2011 22:36:04

Чего-то не даёт мне компилятор такое сделать, как по ссылке. Ругается.
Ну, может он и прав по-своему. Язык-то не зря сильно типизированный.
Сделал в итоге простейший класс, а свою процедуру сделал его методом. И передаю указатель на этот метод.
Alex333
новенький
 
Сообщения: 32
Зарегистрирован: 21.08.2011 19:14:28

Re: Подскажите синтаксис

Сообщение Mr.Smart » 28.11.2011 22:55:44

Alex333 всё прекрасно работает и по сей день. читайте тему до конца.

Добавлено спустя 2 минуты 6 секунд:
приведите "ругань"...
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: Подскажите синтаксис

Сообщение Alex333 » 29.11.2011 08:00:51

Код: Выделить всё
procedure TMyClass.MyProt(const sProt:String);
begin
end;

procedure proc1(const sProt:String;Sender:TObject);
begin
end;

//WrkDir(Utf8ToAnsi(s),FDObj,@MyClass.MyProt);  //Так нормально
WrkDir(Utf8ToAnsi(s),FDObj,@proc1);  //А так ругается


Ругань вот такая:
Код: Выделить всё
SetDates.lpr(53,42) Error: Incompatible type for arg no. 3: Got "<address of procedure(const AnsiString,TObject);Register>", expected "<procedure variable type of procedure(const AnsiString) of object;Register>"
Alex333
новенький
 
Сообщения: 32
Зарегистрирован: 21.08.2011 19:14:28

Re: Подскажите синтаксис

Сообщение Brainenjii » 29.11.2011 09:43:50

Код: Выделить всё
procedure proc1(Sender:TObject; Const sProt:String);
Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Re: Подскажите синтаксис

Сообщение Alex333 » 29.11.2011 14:09:27

Исправил, но легче не стало:

SetDates.lpr(52,42) Error: Incompatible type for arg no. 3: Got "<address of procedure(TObject,const AnsiString);Register>", expected "<procedure variable type of procedure(const AnsiString) of object;Register>"
Alex333
новенький
 
Сообщения: 32
Зарегистрирован: 21.08.2011 19:14:28

Re: Подскажите синтаксис

Сообщение Mr.Smart » 29.11.2011 14:28:15

Код: Выделить всё
procedure proc1(self:TObject; Const sProt:String);
....

var
  m: TMethod;
...
  m.Code:=@Proc1;
  m.Data:=nil;

  MyFunc(TProt(m));
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: Подскажите синтаксис

Сообщение Brainenjii » 29.11.2011 14:41:41

Код: Выделить всё

Unit Unit1;

{$mode objfpc}{$H+}

Interface

Uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs;

Type TMyEvent = Procedure(Sender: TObject; Const aString: String) Of Object;

Type

  { TForm1 }

  TForm1 = Class(TForm)
  Private
    FOnMyEvent: TMyEvent;
    { private declarations }
  Public
    { public declarations }
    Procedure HelloWorld(Const aMessage: String);
    Property OnMyEvent : TMyEvent Read FOnMyEvent Write FOnMyEvent;
    constructor Create(TheOwner: TComponent); override;
  End;

Var
  Form1: TForm1;

Implementation

Procedure MyClick(Self, Sender: TObject);
Begin
  TForm1(Self).HelloWorld('Hello world');
End;

Procedure MyEvent(Self, Sender : TObject; Const aString: String);
Begin
  ShowMessage(aString);
End;

{$R *.lfm}

{ TForm1 }

Procedure TForm1.HelloWorld(Const aMessage: String);
Begin
  If Assigned(FOnMyEvent) Then FOnMyEvent(Self, aMessage);
  Caption := 'Hello World'
End;

Constructor TForm1.Create(TheOwner: TComponent);
Var
  aMyEvent, aClick: TMethod;
Begin
  Inherited Create(TheOwner);
  aMyEvent.Data := nil;
  aMyEvent.Code := @MyEvent;
  OnMyEvent := TMyEvent(aMyEvent);

  aClick.Data := Self;
  aClick.Code := @MyClick;
  OnClick := TNotifyEvent(aClick);
End;

End.

^_^
Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Re: Подскажите синтаксис

Сообщение Alex333 » 29.11.2011 17:58:04

Код: Выделить всё
var
  m: TMethod;
...
  m.Code:=@Proc1;
  m.Data:=nil;
  MyFunc(TProt(m));


Спасибо - это работает. Большой практической надобности уже не было, но любопытно же. Т.е. что же получается - указатель на метод - это на самом деле указатель на запись вот такого вида?
TMethod = record
Code, Data : Pointer;
end;

Или же в стек копируется сама запись, а не указатель? (я просто не знаю, как происходит приведение типа TProt(m) )

Добавлено спустя 5 часов 51 минуту 55 секунд:
Да, посмотрел в ассемблере - в стек копируется именно запись, т.е. 2 указателя, содержащиеся в ней (правда, в FP я ассемблера что-то не понимаю - непривычный, но в Delphi это выглядит так:)
Код: Выделить всё
;m.code:=@proc1
mov    [ebp-$24],$004537e0   
;m.data:=Nil
xor   eax,eax         
mov   [ebp-$20],eax
;WrkDir(TMyProt(m))
push   dword ptr [ebp-$20]
push   dword ptr [ebp-$24]
call   WrkDir

т.е. обычным адресом процедуры это не заменишь, хоть какие параметры внутри напиши.
Alex333
новенький
 
Сообщения: 32
Зарегистрирован: 21.08.2011 19:14:28

Re: Подскажите синтаксис

Сообщение AlexVinS » 30.11.2011 02:09:53

Alex333 писал(а):
Спасибо - это работает. Большой практической надобности уже не было, но любопытно же. Т.е. что же получается - указатель на метод - это на самом деле указатель на запись вот такого вида?
TMethod = record
Code, Data : Pointer;
end;

Или же в стек копируется сама запись, а не указатель? (я просто не знаю, как происходит приведение типа TProt(m) )


Сама запись.
Аватара пользователя
AlexVinS
новенький
 
Сообщения: 95
Зарегистрирован: 27.01.2009 01:18:01


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 7

Рейтинг@Mail.ru