Главная страница
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.041 c
15-1166631451
IMHO
2006-12-20 19:17
2007.01.14
"Война - войной, а обед - по расписанию"


2-1166641119
Signate
2006-12-20 21:58
2007.01.14
Манипуляции с TSocket...


15-1166974212
volodiya
2006-12-24 18:30
2007.01.14
!!!Помогите пожалуйста!!!


9-1141572255
VolanD666
2006-03-05 18:24
2007.01.14
Collision Detection && SpeedFactor


2-1166952333
nordic3
2006-12-24 12:25
2007.01.14
Замена символа в Memo