Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Вместо локальной функции как параметра [D7, XP]


Vovan #2 ©   (2006-12-21 14:45:00) 

Задача.

Есть некоторая функция, которая принимает в качестве параметра имя графического файла, открывает его (например, в TBitmap) и вызывает другую процедуру обработки, которая вернёт некоторые данные об этом изображении через изменяемый параметр. Эта процедура сделана универсально - она не работает с конкретным типом графического контейнера, а осуществляет доступ к пикселям через функцию вида GetPixel(x,y: Integer): Integer, переданную в качестве параметра в процедуру.

Загвоздка в том, что нужно где-то написать эту функцию доступа к пикселям, но Delphi не даёт использовать локальную функцию. А если выносить, то и объект-контейнер должен оказаться вне большой функции, а кто о нём заботиться будет.

Вопрос. Как организовать всё это дело в данном случае?


Vovan #2   (2006-12-25 17:06:00) [1]

Я не понимаю, почему вызов
Obrabotka(Result, @GetPixel, TempBmp);
как в [9] без @ выдаёт ошибку о несовместимости типов, а с @ - нет?


ors_archangel   (2006-12-21 15:48:00) [2]

Я имел в виду

type
TGetPixelProc = function(obj: TObject; x, y: Integer): Integer; // универсально

procedureObrabotka( varRS: TMyResult; callGetPixel: TGetPixelProc; param: TObject);
begin
{ здесь любое обращение к GetPixel выглядет так: }
 GetPixel(param,x,y)
end;

functionObrabotkaOfBitmap: TMyResult;
var
TempBmp: TBitmap;

functionGetPixel(bmp: TBitmap; x,y: Integer): Integer;
begin
  ifbmp.Canvas.Pixels[x,y] = clWhite then
    Result := Zero elseResult := 1;
end;

begin
 Obrabotka(Result, @GetPixel, TempBmp);
end;


ors_archangel   (2006-12-21 15:39:00) [3]

Здесь можно изменить GetPixel - передавать дополнительный параметр, определяющий контейнер, т.о. функция, которая вызывает GetPixel будет передавать ему дополнительный параметр, но всё так же останется универсальной?
Мне то ж такие грабли часто мешали. Думаю, дело в том, что локальные процедуры как бы закреплены в некотором локальном пространстве имён, т.е. локальная функция имеет доступ к локальным переменным функции, по отношению к которой она является локальной, но, когда данная функция вызывается на другом уровне пространства имён, любой доступ к внешним (не глобальным) переменным может оказаться ошибочным, т.к. доступ к локальным переменным происходит по косвенной адрессации типа [ebp+xx], с другой стороны, допустим, функция LocFunc - локальна относительно функции ExFunc, во время существования (доступности) LocFunc область локальной памяти ExFunc фиксировано в памяти (внутри стека), поэтому, если бы функция могла узнать адрес любой родительской (не по вызовам, а иеархически) локальной обалсти памяти, то при досупе к внешним переменным вместо адрессации [ebp+xx] можно было бы использовать адрессацию по этому адресу, взятом в качестве базы, т.е. для решения проблемы в данном виде нужно иметь, например, односвязанный список, хранящий адреса локальных областей переменных, причём этот список может генерироваться только во время выполнения, и заполняться его элементы должны при входе в функцию (например, в прологе), это довольно рассточительно, но так можно было бы сделать использование локальных функций более ортогональным в отношении ко глобальным?


MBo   (2006-12-21 15:20:00) [4]

>Можно попробовать.
Приведенный мной пример работает позволяет обойти ограничение компилятора, но, наверно, стоит идеологию все же поменять.
Мне не вполне ясна картина того, что ты хочешь сделать, но загляни, как сделано обращение к пикселам в зависимости от цветового формата тут:
http://www.delphimaster.ru/articles/pixels/index.html


Vovan #2   (2006-12-21 15:15:00) [5]

>MBo © (21.12.06 15:09) [4]

Можно попробовать. Но всё равно, как переделать так, чтобы:
а) Сохранить универсальность обработки (не писать кучу override).
б) Не возиться с освобождением объектов???


Vovan #2   (2006-12-21 15:11:00) [6]

>А процедура объявлена как of object?

Нет.


type
 TGetPixelProc = function (x, y: Integer): Integer;

procedure Obrabotka(var RS: TMyResult; callGetPixel: TGetPixelProc);

function ObrabotkaOfBitmap: TMyResult;
var
 TempBmp: TBitmap;

 function GetPixel(x,y: Integer): Integer;
 begin
   if TempBmp.Canvas.Pixels[x,y] = clWhite then
     Result := Zero else Result := 1;
 end;

begin
  Obrabotka(Result, GetPixel);
end;


MBo   (2006-12-21 15:09:00) [7]

внутренние (локальные) функции действительно нельзя (опасно) использовать в качестве процедурных параметров, однако если очень хочется:

function Calc(a: Integer; func: TАunc): Integer;
begin
 Result := 3* func(a);
end;

procedure TForm17.Button2Click(Sender: TObject);

function F(a: Integer): Integer;
begin
 Result := a + 10;
end;

begin
 Caption := IntToStr(Calc(1, @F));
end;


tesseract   (2006-12-21 15:02:00) [8]

А процедура объявлена как of object?


Vovan #2   (2006-12-21 14:57:00) [9]

Так и заявляет.

[гога] Local procedure/function GetPixel assigned to procedure variable


Сергей М.   (2006-12-21 14:54:00) [10]


> Delphi не даёт использовать локальную функцию


Это как ?

Прямо так и заявляет, мол, не даю и всё тут ?!

Экая скромница она, однако)


Наверх

Титульная страница Поиск, карта сайта Написать письмо