Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.03.2024, 14:50   #1
killzone
 
Регистрация: 25.03.2010
Сообщений: 6
По умолчанию Передача функции через указатель. Функция вызывается но параметры функции при передаче искажаются

Уважаемые форумчане, приветствую! Я всю голову сломал. Уже большая программа, много модулей. Всё вроде бы хорошо, но видимо шагнул в малопонятное для меня поле. И не могу понять в чем проблема. Код был корректный и рабочий до тех пор пока я не решил передавать функцию как указатель.
У меня в одном из модулей есть такая функция (она рабочая, все ок), суть ее понятно из названия, по коду элемента она выводит его текст:
Код:
function gm_GetTextNameByCode(code:TIntType):String;
var
  return:String;
begin
  return := '';
  TableOfImport.GetTableByName(TABLE_TYPESMARKSGENERAL_NAME).SetCurrentCode(code);
  if TableOfImport.GetTableByName(TABLE_TYPESMARKSGENERAL_NAME).GetCurrentCode <> ERROR_INTEGER then
    return := TableOfImport.GetTableByName(TABLE_TYPESMARKSGENERAL_NAME).GetSpecificInfo('textName');
  Result := return;
end;
В другом модуле у меня инициализируется класс, который занимается обработкой Grid'ов (далее обработчик). Дело в том, что у меня много Grid'ов на форме, и каждый обработчик Grid'а должен использовать свою функцию. В данном случае этот конкретный обработчик Grid'а использует вышеуказанную функцию gm_GetTextNameByCode.
Код:
    GridControlledGeneralMarksHandler := TGridHandler.Create(Form_KVYD.Grid_ControlledGeneralMarks,
      cntrlTable, cntrlCode, CURRENT_CODE, TABLE_MARKSGENERAL_NAME,
        [TABLE_TYPESMARKSGENERAL_NAME], @gm_GetTextNameByCode, [tpPopup, tpString], ['type', 'textMark']);
Обратите внимание на то, что выделено красным. Хочу через указатель передать нужную функцию при инициализации обработчика. Чтобы минимум править код в дальнейшем. (до этого я не использовал указатель на функцию, я просто в самом классе обработчике явно указывал какую именно функцию использовать). Но повторюсь, у меня будет много Grid'ов, с каждым из которых будет работать отдельный обработчик. Но не хочется для каждого конкретного обработчика Grid'а менять код. Хочется сделать один обработчик Grid'а с универсальным кодом, чтобы менять только параметры в конструкторе обработчика при создании.

Вот так выглядит тип моей функции:
Код:
type TFunctionGetTextByCode = function (var code: TIntType): String;
TIntType это Int64; Можете и не спрашивать зачем я так сделал

В самом обработчике грида есть такой конструктор
Код:
constructor Create(cmpn: TComponent; tbl: String; spInfo: String;  cCode:TIntType; 
gTbl: String;  pTbls:TArrayOfString; pTblFuncs: TFunctionGetTextByCode; colTypes:TArrayOfTDataType; colNames: TArrayOfString);
и есть такая процедурка, которая инициализирует раскрывающийся список
Код:
procedure TGridHandler.Grid_InitPopups;
var
  i, current:Integer;
  popCode: TIntType;
  iterator: TTableRecordsIterator;
begin
  current := 0;
  for i := 0 to High(Self.columnTypes) do
    if Self.columnTypes[i] = tpPopup then
    begin
      try
        iterator := TTableRecordsIterator.Create(Self.popupTables[current], True, '', ERROR_INTEGER);
        while iterator.hasNext do
        begin
          popCode := iterator.next;
          ((Self.component as TGrid).Content.Children.Items[i] as TPopupColumn).Items.Add(Self.popupFuncGetTextBycode(popCode));
        end;
        current := current + 1;
      finally
        if Assigned(iterator) then FreeAndNil(iterator);
      end;
    end;
end;

popupFuncGetTextBycode это и есть моя функция gm_GetTextNameByCode которую я передавал указателем. И код работает, никаких ошибок не происходит, но тут самое интересное: popCode равна к примеру 4, а вот когда запускается функция gm_GetTextNameByCode то у нее в параметрах запуска почему-то уже не 4, а какое-то огромное число 886826134832. Уже нервный тик у меня. Как же сделать чтобы работало корректно?

До этого у меня вместо строчки с функцией которая выделена красным, было вот так:
Код:
((Self.component as TGrid).Content.Children.Items[i] as TPopupColumn).Items.Add(gm_GetTextNameByCode(popCode));
И все хорошо работало. Если передавался код 4, то и функция получала 4, как положено.

Последний раз редактировалось killzone; 11.03.2024 в 15:13.
killzone вне форума Ответить с цитированием
Старый 11.03.2024, 17:28   #2
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

А вот такой пример у вас работает?
Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    btn1: TButton;
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TIntType = Int64;
  TFunctionGetTextByCode = function(var code: TIntType): string;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function one(var code: TIntType): string;
begin
  result := IntToStr(code);
end;

function two(var code: TIntType): string;
begin
  result := IntToStr(code + 1);
end;

procedure CallFunc(f: TFunctionGetTextByCode);
var
  v: TIntType;
begin
  v := 4;
  ShowMessage(f(v));
end;

procedure TForm1.btn1Click(Sender: TObject);
begin
  CallFunc(one);
  CallFunc(two);
end;

end.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA на форуме Ответить с цитированием
Старый 11.03.2024, 23:20   #3
killzone
 
Регистрация: 25.03.2010
Сообщений: 6
По умолчанию

Да, такой пример у меня работает.
Попробовал воссоздать свою ситуацию.
Код:
unit Unit2;

interface
uses Vcl.Dialogs;

type
  TIntType = Int64;
  TFunctionGetTextByCode = function(var code: TIntType): string;

  testHandler = class
    myFunc : TFunctionGetTextByCode;
    constructor Create(func:TFunctionGetTextByCode);

    procedure bamby(code:TIntType);
  end;


implementation

constructor testHandler.Create(func:TFunctionGetTextByCode);
begin
  inherited Create;
  Self.myFunc := func;
end;

procedure testHandler.bamby(code:TIntType);
begin
  ShowMessage(Self.myFunc(code));
end;

end.
Код:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Unit2;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function one(var code: TIntType): string;
begin
  result := IntToStr(code);
end;

function two(var code: TIntType): string;
begin
  result := IntToStr(code + 1);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  tHandle1, tHandle2 :testHandler;
  v1, v2: TIntType;
begin
  try
    tHandle1 := testHandler.Create(@one);
    tHandle2 := testHandler.Create(@two);
    v1 := 4;
    v2 := 10;
    tHandle1.bamby(v1);
    tHandle2.bamby(v2);
  finally
    if Assigned(tHandle1) then FreeAndNil(tHandle1);
    if Assigned(tHandle2) then FreeAndNil(tHandle2);
  end;
end;


end.
И, тоже работает. Но у меня в основной программе, в дебаггере, я попадаю на синюю строчку у которой v1 = 4, далее перехожу на голубую строчку у которой code по идее тоже должен быть равен 4, а число совсем огромное. Как же такое может быть. Хм, неужели баг делфи какой-то.
killzone вне форума Ответить с цитированием
Старый 12.03.2024, 07:15   #4
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,777
По умолчанию

Цитата:
Код:
function gm_GetTextNameByCode(code:TIntType):String;
Цитата:
Код:
type TFunctionGetTextByCode = function (var code: TIntType): String;
Я вижу тут РАЗНЫЕ функции, с var и без var.
Vapaamies вне форума Ответить с цитированием
Старый 12.03.2024, 07:36   #5
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

Vapaamies, действительно. Без @ компилятор бы выявил ошибку "[Error]: Incompatible types: 'Parameter lists differ'".
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )

Последний раз редактировалось BDA; 12.03.2024 в 07:39.
BDA на форуме Ответить с цитированием
Старый 12.03.2024, 13:18   #6
killzone
 
Регистрация: 25.03.2010
Сообщений: 6
По умолчанию

Цитата:
Сообщение от Vapaamies Посмотреть сообщение
Я вижу тут РАЗНЫЕ функции, с var и без var.
Блин, я сколько раз смотрел на тип и даже ничего не ёкнуло ни разу. Спасибо, теперь всё работает корректно.
Видимо, то самое огромное число, это был адрес переменной, ссылка.
killzone вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
При перенаправление запроса искажаются параметры ArtGrek Работа с сетью в Delphi 2 18.01.2017 11:04
Передача функции в качестве аргумента через указатель Ka2R Помощь студентам 17 17.03.2015 16:20
Из функции вернуть данные через входящие параметры. Не возвращает, хоть тресни. Человек_Борща Общие вопросы Delphi 6 08.07.2012 22:35
Не получается получить значение из функции через указатель Casper-SC Общие вопросы C/C++ 5 12.01.2012 06:32
Создать массив в функции, через указатель. Как? TwiX Общие вопросы Delphi 10 01.04.2010 11:36