Процедура как параметр

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

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

Процедура как параметр

Сообщение Prof » 04.05.2007 13:30:30

Коллеги, подскажите!
Как организовать на FPC (v.1 для Linux)
передачу имени процедуры Pa через
список формальных параметров
функции Fb. Причем
Fb - определяется в нек. unit-e
Pa - определяется в нек.программе, которая, естественно,
подключает unit через uses.
Не могу добиться проку от документации.
Похоже, что дело в режимах/псевдокомментариях.
Prof
новенький
 
Сообщения: 14
Зарегистрирован: 27.09.2006 16:25:13

Сообщение Иван Шихалев » 04.05.2007 13:44:33

Объявляем процедурный тип, да и всё… В чём проблема-то?
Аватара пользователя
Иван Шихалев
энтузиаст
 
Сообщения: 1138
Зарегистрирован: 15.05.2006 11:26:13
Откуда: Екатеринбург

Сообщение Prof » 04.05.2007 14:06:53

Иван Шихалев писал(а):Объявляем процедурный тип, да и всё… В чём проблема-то?

Дело в том, что процедурный тип приходится описывать в unit-e.
А в программе (на месте вызова Fa) компилятор отказывается
признавать имя фактческой процедуры, соответствующей
процедурному типу.
Сразу скажу, что с точки зрения синтаксиса все корректно,
и на TP это работает.
Prof
новенький
 
Сообщения: 14
Зарегистрирован: 27.09.2006 16:25:13

Сообщение Иван Шихалев » 04.05.2007 14:14:41

Пример, плиз. В разных режимах передача и вызов процедурных типов действительно работает по разному.
Аватара пользователя
Иван Шихалев
энтузиаст
 
Сообщения: 1138
Зарегистрирован: 15.05.2006 11:26:13
Откуда: Екатеринбург

Сообщение Prof » 04.05.2007 18:53:52

Иван Шихалев писал(а):Пример, плиз. В разных режимах передача и вызов процедурных типов действительно работает по разному.


Вот "чистый" случай:
----------------------------------------файл un.pp ----------------------------
{$SMARTLINK ON}
unit un;
interface
type TPr = procedure(N : integer);
function Ask(M : integer; Pr : TPr) : boolean;
implementation
function Ask(M : integer; Pr : TPr) : boolean;
begin Pr(M); Ask:=true end;
end.
----------------------------------------файл tt.pp -----------------------------
program tt;
uses un;
procedure One(N : integer);
begin writeln(N) end;
procedure Fis;
begin if Ask(4,One) then; end;
begin Fis
end.
------------------------------------------------------------------------------------
При компиляции tt.pp выдается:
Error: Wrong amount of parameters specified
Prof
новенький
 
Сообщения: 14
Зарегистрирован: 27.09.2006 16:25:13

Сообщение Alexander » 04.05.2007 20:31:28

А для режима Delphi нужно поступать иначе.

Код: Выделить всё
{$SMARTLINK ON}
{$MODE FPC}
unit un;

interface

type TPr = procedure(N : integer); stdcall;

function Ask(M : integer; Pr : TPr) : boolean;

implementation

function Ask(M : integer; Pr : TPr) : boolean;
begin
Pr(M);
Ask:=true;
end;
end.


Код: Выделить всё
{$MODE FPC}
program tt;

uses un;

procedure One(N : integer); stdcall;
begin
writeln(N);
end;

procedure Fis;
begin
if Ask(4, @One) then;
end;

begin
Fis;
end.
Аватара пользователя
Alexander
энтузиаст
 
Сообщения: 821
Зарегистрирован: 18.12.2005 19:10:00
Откуда: оттуда

Сообщение STAKANOV » 04.05.2007 20:35:09

Код: Выделить всё
program tt;
uses un;
procedure One(N : integer);
begin writeln(N) end;
procedure Fis;
begin if Ask(4,@One) then; end;
begin Fis
end.


См. [url]http://freepascal.ru/wiki/index.php/Процедурные_типы[/url]
Аватара пользователя
STAKANOV
энтузиаст
 
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград

Сообщение Prof » 07.05.2007 16:23:34

СПАСИБО КОЛЛЕГИ!
ТЕПЕРЬ РАБОТАЕТ!
Prof
новенький
 
Сообщения: 14
Зарегистрирован: 27.09.2006 16:25:13

Re: Процедура как параметр

Сообщение VirtUX » 04.09.2009 14:57:11

Не стал создавать новую тему, т.к. заголовок темы, в принципе, подходит.
Ситуация следующая:
В модуле не используются никакие объекты заранее объявленные. Но создаются по мере необходимости. Нужно созданному объекту в событие OnClick передать процедуру невидимую из других модулей. Я пытаюсь сделать это так:
Код: Выделить всё
unit uDialogs;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, StdCtrls, Controls;

  procedure DiagDubleFiltr(const Capt, Mess: UTF8String; var Res1, Res2: UTF8String);

implementation

var FormDialogs: TForm;

procedure ClearForm;
var i: integer;
begin
  if FormDialogs.ControlCount > 0 then
    for i := 0 to pred(FormDialogs.ControlCount) do FormDialogs.Controls[i].Free;
end;

procedure DiagDubleFiltr(const Capt, Mess: UTF8String; var Res1, Res2: UTF8String);
var LabelMess: TLabel;
    EditFiltr1, EditFiltr2: TEdit;
    ButtOK: TButton;

    procedure ButtOKDubleFiltr(Sender: TObject);
    begin
      Res1 := EditFiltr1.Text;
      Res2 := EditFiltr2.Text;
      FormDialogs.Hide;
      ClearForm;
    end;

begin
  FormDialogs := TForm.Create(Application);
  FormDialogs.Caption:= Capt;
  LabelMess := TLabel.Create(FormDialogs);
  LabelMess.Parent := FormDialogs;
  LabelMess.Caption:= Mess;
  LabelMess.Align:= alTop;
  LabelMess.WordWrap:= true;
  LabelMess.BorderSpacing.Around:= 5;
  LabelMess.Show;
  EditFiltr1 := TEdit.Create(FormDialogs);
  EditFiltr1.Parent := FormDialogs;
  EditFiltr1.Align:= alTop;
  EditFiltr1.BorderSpacing.Around:= 5;
  EditFiltr1.Show;
  EditFiltr2 := TEdit.Create(FormDialogs);
  EditFiltr2.Parent := FormDialogs;
  EditFiltr2.Align:= alTop;
  EditFiltr2.BorderSpacing.Around:= 5;
  EditFiltr2.Show;
  ButtOK := TButton.Create(FormDialogs);
  ButtOK.Parent := FormDialogs;
  ButtOK.Align:= alTop;
  ButtOK.BorderSpacing.Around:= 5;
  ButtOK.Caption:= 'OK';
  ButtOK.OnClick:= @ButtOKDubleFiltr;      //Здесь возникает ошибка об несоответствии типов, что мол нельзя передавать локальную процедуру
  ButtOK.Show;
  FormDialogs.AutoSize:= true;
  FormDialogs.ShowModal;
end;

end.

Как обойти этот запрет?
Lazarus 0.9.29
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

Re: Процедура как параметр

Сообщение v-t-l » 04.09.2009 15:28:09

Обработчик события не может быть вложенной процедурой. Более того - он должен быть методом какого-нибудь класса.
Код: Выделить всё
{ Standard events }

  TNotifyEvent = procedure(Sender: TObject) of object;
v-t-l
энтузиаст
 
Сообщения: 740
Зарегистрирован: 13.05.2007 16:27:22
Откуда: Belarus

Re: Процедура как параметр

Сообщение Mr.Smart » 04.09.2009 15:37:38

Механиз присваивания событию объекта обычной процедуры следующий:
Код: Выделить всё
procedure TestClick(Sender: TObject);
begin
  ShowMessage('OK!');
end;

...
var
  m: TMethod;
...
  m.Code:=@TestClick;
  m.Data:=nil;
  Button1.OnClick:=TNotifyEvent(m);
...

Структура TMethod имеет следующие поля:
  • Code - адрес процедуры/функции;
  • Data - значение первого "скрытого" параметра т.н. Self
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: Процедура как параметр

Сообщение Max Rusov » 04.09.2009 15:43:00

Mr.Smart

Так делать нельзя. Аргументы будут передаваться неправильно.
Max Rusov
постоялец
 
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Re: Процедура как параметр

Сообщение Mr.Smart » 04.09.2009 15:52:03

Max Rusov
Да действительно ошибся :oops:
Процедура или функция должна содержать на один параметр больше
Код: Выделить всё
procedure TestClick(Self, Sender: TObject);
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: Процедура как параметр

Сообщение VirtUX » 05.09.2009 15:35:17

Mr.Smart писал(а):Max Rusov
Да действительно ошибся :oops:
Процедура или функция должна содержать на один параметр больше
Код: Выделить всё
procedure TestClick(Self, Sender: TObject);

Я обошелся одним параметром:
Код: Выделить всё
procedure TestClick(Self: TObject);

Так тоже работает. Спасибо за помощь.
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

Re: Процедура как параметр

Сообщение Mr.Smart » 06.09.2009 11:43:16

VirtUX писал(а):Я обошелся одним параметром:
...
Так тоже работает. Спасибо за помощь.

Работать то оно будет, но в стек передаются именно 2 параметра Self и Sender!
Так что для того чтобы ненарушить целосность стека нужно использовать прицедуры/функции с правельным числом параметров.
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

След.

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

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

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5

Рейтинг@Mail.ru