Вопрос про процедурный тип

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

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

Вопрос про процедурный тип

Сообщение beria » 25.12.2016 01:20:35

Код: Выделить всё
program test2;
type
  THookMonitorOfObject = procedure(const Buffer: string) of object;
  Main = class(TObject)
    str:      string;
    procmain: THookMonitorOfObject;
    constructor Create();
    procedure HookMonitor(const Buffer: string);
    procedure HookWrite;
  end;
  constructor Main.Create();
  begin
    inherited;
    str := 'test';
  end;
  procedure main.HookMonitor(const Buffer: string);
  begin
    writeln(Buffer);
    readln;
  end;
  procedure main.HookWrite;
  begin
    procmain := @HookMonitor;
    procmain(str);
  end;
  procedure main.HookMonitor(const Buffer: string);
  begin
    writeln(Buffer);
  end;
var
  My: main;
begin
  My.Create;
  My.HookWrite;
  My.Free;
end.               



Выдает ошибку при запуске.
При этом просто procmain := HookMonitor; , какого-то х. , не компилируется
Вопрос - в чем у меня ошибка.
зы: данный пример чисто абстрактный, но столкнулся с таким при написании большой программы, а альтернативным способом решать очень не хочется ибо уже большая рабочая структура отлажена.
ззы: мануал читал.
Последний раз редактировалось beria 25.12.2016 02:56:49, всего редактировалось 1 раз.
Аватара пользователя
beria
постоялец
 
Сообщения: 130
Зарегистрирован: 29.09.2016 08:57:13

Re: Вопрос про процедурный тип

Сообщение Sharfik » 25.12.2016 01:35:56

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

{$mode objfpc}{$H+}

interface

uses
Classes;

type
  THookMonitorOfObject = procedure(const Buffer: string) of object;
  Main = class(TObject)
  public
    str:      string;
    procmain: THookMonitorOfObject;
    constructor Create;
    procedure HookMonitor(const Buffer: string);
    procedure HookWrite;
  end;

implementation

  constructor Main.Create;
  begin
    inherited;
    str := 'test';
  end;
  procedure main.HookMonitor(const Buffer: string);
  begin
    writeln(Buffer);
    readln;
  end;

  procedure main.HookWrite;
  begin
    procmain := @HookMonitor;
    procmain(str);
  end;

  procedure HookMonitor(const Buffer: string);
  begin
    writeln(Buffer);
  end;

var
  My: main;
begin
  My.Create;
  My.HookWrite;
  My.Free;
end.           

может так?
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 759
Зарегистрирован: 20.07.2013 01:04:30

Re: Вопрос про процедурный тип

Сообщение beria » 25.12.2016 02:10:24

Sharfik писал(а):может так?

Много хуже ибо даже не компилируется ибо во первых interface/implementation в теле основного модуля не нужны, а {$mode objfpc}{$H+} и так включено по дефолту, поскольку без этого в любом случае компиляция не возможна.

Вопрос остается, что я не так понимаю в процедурных переменных внутри класса. Я в печали...
Аватара пользователя
beria
постоялец
 
Сообщения: 130
Зарегистрирован: 29.09.2016 08:57:13

Re: Вопрос про процедурный тип

Сообщение runewalsh » 25.12.2016 04:26:06

My не инициализирован, вместо My.Create должно быть My := Main.Create.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

Re: Вопрос про процедурный тип

Сообщение beria » 25.12.2016 05:25:51

runewalsh писал(а):My не инициализирован, вместо My.Create должно быть My := Main.Create.


Спасибо добрый человек. Такая глупая ошибка...

Кстати нашел в коде ещё одну вещь, которая при определенных обстоятельствах, на которые я тоже смог налететь, могла привести к сбою или невозможности компиляции...
Итоговый и заведомо рабочий вариант, кому интересно

Код: Выделить всё
program test2;
type
  THookMonitorOfObject = procedure(const Buffer: string) of object;
  Main = class(TObject)
    str:      string;
    procmain: THookMonitorOfObject;
    constructor Create();
    procedure HookMonitor(const Buffer: string);
    procedure HookWrite;
  end;
  constructor Main.Create();
  begin
    inherited;
    str := 'test';
  end;
  procedure main.HookMonitor(const Buffer: string);
  begin
    writeln(Buffer);
    readln;
  end;
  procedure main.HookWrite;
  begin
    procmain  := THookMonitorOfObject(@HookMonitor);
    procmain(str);
  end;
var
  My: main;
begin
  My := Main.Create;
  My.HookWrite;
  My.Free;
end.
Аватара пользователя
beria
постоялец
 
Сообщения: 130
Зарегистрирован: 29.09.2016 08:57:13

Re: Вопрос про процедурный тип

Сообщение runewalsh » 25.12.2016 06:59:42

>THookMonitorOfObject(@HookMonitor)
Не советую так делать, FPC приводит без проверок:
Код: Выделить всё
type
   ProcA = procedure;
   ProcB = procedure(const s: string);

   procedure NotAnA(const s: string);
   begin
      ShowMessage(s);
   end;

var
   a: ProcA;

begin
   a := @NotAnA; // Error: incompatible types
   a := ProcA(@NotAnA); // компилируется — а зря
   a();
end.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

Re: Вопрос про процедурный тип

Сообщение beria » 25.12.2016 10:18:45

runewalsh писал(а):
Re: Вопрос про процедурный тип

Непрочитанное сообщение runewalsh » 25.12.2016 06:59:42
>THookMonitorOfObject(@HookMonitor)
Не советую так делать, FPC приводит без проверок:



Тогда объясните что делать, если уже в реальном коде
Sock.OnReadFilter := @Monitor2;
выдает при компиляции Error: Hесовместимые типы: полyчено "<procedure variable type of procedure(TObject;var AnsiString) of object;Register>", ожидалось "BLCKSOCK.<procedure variable type of procedure(TObject;var AnsiString) of object;Register>"


Sock.OnReadFilter := THookDataFilter(@Monitor2);
прекрасно работает как надо?

И в тему:
Sock.OnReadFilter := Monitor2;
выдает Error: Неверное количество паpаметpов при вызове "Monitor2".
При том что параметры типа и метода заведомо одинаковые.
procedure Monitor2(Sender: TObject; var Value: ansistring) и
THookDataFilter = procedure(Sender: TObject; var Value: AnsiString) of object;
Аватара пользователя
beria
постоялец
 
Сообщения: 130
Зарегистрирован: 29.09.2016 08:57:13

Re: Вопрос про процедурный тип

Сообщение скалогрыз » 25.12.2016 10:31:55

ты уверен, что у тебя Monitor2 как раз of object? он у тебя к какому классу принадлежит?

в частности. Рекомендую синтаксис модуля выстанавливать заранее и явно:
Код: Выделить всё
{$mode objfpc}

либо
Код: Выделить всё
{$mode delphi}

внесёт существенную разницу в то, как будут присваиваться значения процедур.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Вопрос про процедурный тип

Сообщение beria » 25.12.2016 10:37:27

скалогрыз писал(а): к какому классу принадлежит?

Там всего один класс и его метод Monitor2 и его же унаследованная переменная Sock с полем OnReadFilter типа THookDataFilter
Последний раз редактировалось beria 25.12.2016 10:39:22, всего редактировалось 1 раз.
Аватара пользователя
beria
постоялец
 
Сообщения: 130
Зарегистрирован: 29.09.2016 08:57:13

Re: Вопрос про процедурный тип

Сообщение скалогрыз » 25.12.2016 10:38:23

оке.
добавь
Код: Выделить всё
{$mode delphi}

в начало модуля (сразу после unit или program)

Компилируется:
Код: Выделить всё
program test2;
{$mode delphi}
type
  THookMonitorOfObject = procedure(const Buffer: string) of object;
  Main = class(TObject)
    str:      string;
    procmain: THookMonitorOfObject;
    constructor Create();
    procedure HookMonitor(const Buffer: string);
    procedure HookWrite;
  end;
  constructor Main.Create();
  begin
    inherited;
    str := 'test';
  end;
  procedure main.HookMonitor(const Buffer: string);
  begin
    writeln(Buffer);
    readln;
  end;
  procedure main.HookWrite;
  begin
    procmain  := HookMonitor;
    procmain(str);
  end;
var
  My: main;
begin
  My := Main.Create;
  My.HookWrite;
  My.Free;
end.


Компилируется 2:
Код: Выделить всё
program test2;
{$mode objfpc}
type
  THookMonitorOfObject = procedure(const Buffer: string) of object;
  Main = class(TObject)
    str:      string;
    procmain: THookMonitorOfObject;
    constructor Create();
    procedure HookMonitor(const Buffer: string);
    procedure HookWrite;
  end;
  constructor Main.Create();
  begin
    inherited;
    str := 'test';
  end;
  procedure main.HookMonitor(const Buffer: string);
  begin
    writeln(Buffer);
    readln;
  end;
  procedure main.HookWrite;
  begin
    procmain  := @HookMonitor;
    procmain(str);
  end;
var
  My: main;
begin
  My := Main.Create;
  My.HookWrite;
  My.Free;
end.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Вопрос про процедурный тип

Сообщение beria » 25.12.2016 10:44:49

скалогрыз писал(а):ачало модуля (сразу после unit или program)


Sock.OnReadFilter := @Monitor2; project.pas(148,29) Error: Ожидается идентификатор переменной
Sock.OnReadFilter := Monitor2; project.pas(149,30) Error: Hесовместимые типы: полyчено "THTML.Monitor2(TObject;var AnsiString);", ожидалось "<procedure variable type of procedure(TObject;var AnsiString) of object;Register>"
Sock.OnReadFilter := THookDataFilter(@Monitor2); project.pas(147,43) Error: Ожидается идентификатор переменной

:shock:

{$mode objfpc}
Sock.OnReadFilter := THookDataFilter(@Monitor2); Ok
Последний раз редактировалось beria 25.12.2016 10:48:25, всего редактировалось 1 раз.
Аватара пользователя
beria
постоялец
 
Сообщения: 130
Зарегистрирован: 29.09.2016 08:57:13

Re: Вопрос про процедурный тип

Сообщение скалогрыз » 25.12.2016 10:47:51

может ты весь project.pas сразу выложишь?

такое чувство, что THTML использует свои типы, не те которые использованы в синапсе.
Где объявлен THTML?

вангую какую-нить хрень,типа
Код: Выделить всё
type
  AnsiString = rawByteString;
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Вопрос про процедурный тип

Сообщение beria » 25.12.2016 10:53:49

Дел
Аватара пользователя
beria
постоялец
 
Сообщения: 130
Зарегистрирован: 29.09.2016 08:57:13

Re: Вопрос про процедурный тип

Сообщение скалогрыз » 25.12.2016 10:56:52

ладно.
поменяй тогда объявление Monitor2 на такое:
Код: Выделить всё
procedure Monitor2(Sender: System.TObject; var Value: System.ansistring);


вообще покажи объявление всего класса, членом которого является Monitor2
Последний раз редактировалось скалогрыз 25.12.2016 10:59:41, всего редактировалось 1 раз.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Вопрос про процедурный тип

Сообщение beria » 25.12.2016 10:58:25

скалогрыз писал(а):вангую какую-нить хрень,типа

Не-а. Я явно определения типов из синапсовской либы копировал... Весь проект никак не выложить, слишком там много связей с кучей разных бибилиотек и модулей , которые физически в куче мест лежат.
По думаю что как раз для objfpc альтернативы нет. Про дельфи -да, но в у меня в дельфи моде сам синапс уже не перекомпилируется....
Аватара пользователя
beria
постоялец
 
Сообщения: 130
Зарегистрирован: 29.09.2016 08:57:13

След.

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

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

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

Рейтинг@Mail.ru