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

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

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

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

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

Сообщение beria »

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

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 01:56:49, всего редактировалось 1 раз.
Аватара пользователя
Sharfik
энтузиаст
Сообщения: 839
Зарегистрирован: 20.07.2013 01:04:30

Сообщение Sharfik »

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

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.           

может так?
Аватара пользователя
beria
постоялец
Сообщения: 130
Зарегистрирован: 29.09.2016 07:57:13

Сообщение beria »

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

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

Вопрос остается, что я не так понимаю в процедурных переменных внутри класса. Я в печали...
Аватара пользователя
runewalsh
энтузиаст
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Сообщение runewalsh »

My не инициализирован, вместо My.Create должно быть My := Main.Create.
Аватара пользователя
beria
постоялец
Сообщения: 130
Зарегистрирован: 29.09.2016 07:57:13

Сообщение beria »

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.
Аватара пользователя
runewalsh
энтузиаст
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Сообщение runewalsh »

>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.
Аватара пользователя
beria
постоялец
Сообщения: 130
Зарегистрирован: 29.09.2016 07:57:13

Сообщение beria »

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;
скалогрыз
долгожитель
Сообщения: 1804
Зарегистрирован: 03.09.2008 02:36:48

Сообщение скалогрыз »

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

в частности. Рекомендую синтаксис модуля выстанавливать заранее и явно:

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

{$mode objfpc}

либо

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

{$mode delphi}

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

Сообщение beria »

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

Там всего один класс и его метод Monitor2 и его же унаследованная переменная Sock с полем OnReadFilter типа THookDataFilter
Последний раз редактировалось beria 25.12.2016 09:39:22, всего редактировалось 1 раз.
скалогрыз
долгожитель
Сообщения: 1804
Зарегистрирован: 03.09.2008 02:36:48

Сообщение скалогрыз »

оке.
добавь

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

{$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.
Аватара пользователя
beria
постоялец
Сообщения: 130
Зарегистрирован: 29.09.2016 07:57:13

Сообщение beria »

скалогрыз писал(а):ачало модуля (сразу после 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 09:48:25, всего редактировалось 1 раз.
скалогрыз
долгожитель
Сообщения: 1804
Зарегистрирован: 03.09.2008 02:36:48

Сообщение скалогрыз »

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

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

вангую какую-нить хрень,типа

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

type
  AnsiString = rawByteString;
Аватара пользователя
beria
постоялец
Сообщения: 130
Зарегистрирован: 29.09.2016 07:57:13

Сообщение beria »

Дел
скалогрыз
долгожитель
Сообщения: 1804
Зарегистрирован: 03.09.2008 02:36:48

Сообщение скалогрыз »

ладно.
поменяй тогда объявление Monitor2 на такое:

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

procedure Monitor2(Sender: System.TObject; var Value: System.ansistring);


вообще покажи объявление всего класса, членом которого является Monitor2
Последний раз редактировалось скалогрыз 25.12.2016 09:59:41, всего редактировалось 1 раз.
Аватара пользователя
beria
постоялец
Сообщения: 130
Зарегистрирован: 29.09.2016 07:57:13

Сообщение beria »

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

Не-а. Я явно определения типов из синапсовской либы копировал... Весь проект никак не выложить, слишком там много связей с кучей разных бибилиотек и модулей , которые физически в куче мест лежат.
По думаю что как раз для objfpc альтернативы нет. Про дельфи -да, но в у меня в дельфи моде сам синапс уже не перекомпилируется....
Ответить