Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.01.14;
Скачать: CL | DM;

Вниз

Вместо локальной функции как параметра   Найти похожие ветки 

 
Vovan #2   (2006-12-21 14:45) [0]

Задача.

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

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

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


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


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


Это как ?

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

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


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

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

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


 
tesseract ©   (2006-12-21 15:02) [3]

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


 
MBo ©   (2006-12-21 15:09) [4]

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

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;


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

>А процедура объявлена как 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;



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

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

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


 
MBo ©   (2006-12-21 15:20) [7]

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


 
ors_archangel ©   (2006-12-21 15:39) [8]

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


 
ors_archangel ©   (2006-12-21 15:48) [9]

Я имел в виду

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

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

function ObrabotkaOfBitmap: TMyResult;
var
TempBmp: TBitmap;

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

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


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

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



Страницы: 1 вся ветка

Текущий архив: 2007.01.14;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.053 c
2-1166529073
~Димас~
2006-12-19 14:51
2007.01.14
Интеграция


15-1167024474
Slider007
2006-12-25 08:27
2007.01.14
С днем рождения ! 23 декабря


2-1166791290
Rolevik
2006-12-22 15:41
2007.01.14
Задание атрибутов музыкальных файлов


2-1166873475
Серый
2006-12-23 14:31
2007.01.14
удаление из stringgrid


3-1161765448
Flash_80
2006-10-25 12:37
2007.01.14
Из Query в Excel?