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

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

Переменные процедурного типа [D7, XP]


Страницы:   1 2 3

checkmate-maker ©   (2008-10-14 12:45:00) 

Здравствуйте, знатоки.
 Помогите, пожалуйста, разобраться с задачей проверки корректности присваивания.
 Имеется код:

...
var
 f: procedure(a0: Integer; a1:String); stdcall;
begin
 @f := GetPtr();
end;

 Функция GetPtr возвращает указатель на процедуру(либо функцию). Если параметры процедуры f идентичны параметрам в возвращенной процедуры, то все нормально. Если совпадение не достигнуто, то ненормально. Как до вызова f определить корректность параметров?
 Спасибо.


oxffff   (2008-10-15 14:14:00) [1]


> Сергей М. ©   (15.10.08 13:10) [51]


Мысли рождаются сами собой.
Например [50] пришла в голову в ванной, когда я мылся после тяжелой физической работы(ремонт дома делаю). Неоднократно замечено, что физический труд очень полезно. Столько мыслей сразу.

:)


Сергей М.   (2008-10-15 13:10:00) [2]


> oxffff


Автор уже забыл свою изначальную затею как страшный сон , а ты все мысли плодишь на эту тему)

Обрати внимание - вопрос вырос из указателя.

А в [28] автор ортогонально развернул оглобли, так что от первоначальная идеи не осталось и следа.

Пилите, Шура, пилите !)


oxffff   (2008-10-14 23:44:00) [3]

Я тут слегка усовершенствовал свою версию
отцепив привязку от провайдера контекста.

TContex=record
a,b:integer;
c:string;
end;

IContextProvider=interface
['{C98B6149-BCCA-432D-B9B8-9066ACDAA253}']
function AssignContext(var Contex:TContex):boolean;
end;

TContextProvider=class(TInterfacedObject,IContextProvider)
protected
function AssignContext(var Contex:TContex):boolean;virtual;abstract;
end;

TContextProvider1=class(TContextProvider)
protected
DataA,DataB:integer;
function AssignContext(var Contex:TContex):boolean;override;
public
constructor create(DataA,DataB:integer);
end;

TContextProvider2=class(TContextProvider)
protected
DataA:integer;
DataC:string;
function AssignContext(var Contex:TContex):boolean;override;
public
constructor create(DataA:integer;DataC:string);
end;

function WorkFunc(Unknown:IUnknown):boolean;
var Contex:TContex;
   ContextProvider:IContextProvider;
begin
try
ContextProvider:=Unknown as IContextProvider;
//Устанавливаем значение по умолчанию
Contex.a:=0;
Contex.b:=0;
Contex.c:='Значение по умолчанию';
//Получаем данные контекста вызова
if ContextProvider.AssignContext(Contex)then
     begin
     showmessage('a='+inttostr(Contex.a)+' b='+inttostr(Contex.b)+' c='+Contex.c);
     result:=true;
     exit;
     end;
except
end;
result:=False;
end;

{ TContextProvider1 }

function TContextProvider1.AssignContext(var Contex: TContex): boolean;
begin
Contex.a:=DataA;
Contex.b:=DataB;
end;

constructor TContextProvider1.create(DataA, DataB: integer);
begin
self.DataA:=DataA;
self.DataB:=DataB;
end;

{ TContextProvider2 }

function TContextProvider2.AssignContext(var Contex: TContex): boolean;
begin
Contex.a:=DataA;
Contex.c:=DataC;
end;

constructor TContextProvider2.create(DataA:integer;DataC:string);
begin
self.DataA:=DataA;
self.DataC:=DataC;
end;

{ TContextProvider }

procedure TForm1.Button1Click(Sender: TObject);
begin
WorkFunc(TContextProvider1.create(1,2));
WorkFunc(TContextProvider2.create(1,'Параметр задан'));
end;


oxffff   (2008-10-14 20:19:00) [4]


> Читай еще раз и внимательно:
>
>
> > Как до вызова f определить корректность параметров?


В run time только TypeInfo поможет до вызова стороне клиента.


oxffff   (2008-10-14 20:15:00) [5]


> Дык о чем тогда базар ?)



> После того как "отцы" ресурса с какого-то бодуна взяли да
> добавили обязательный 3-й параметрпри запросах к ресурсу,
>  стало:
> someproto://somedomain/someresource?param1=A?param2=B?param3=C
> А я ничего не зная об этом по-прежнему запрашиваю с 2-мя
>
> параметрами.
>  
> Кто ответственен за возможную коррекцию моей ошибки или
>
> корректный отлуп запроса ?
> Разумеется, сервер (вызываемый код) ! Не браузер же (вызывающий
>
> код) !
> Иначе на каждый чих "отцов" придется переписывать каждый
>
> браузер)


Да почему базар?  

А у меня встречный вопрос. Вы [37] спрашивали про третий обязательный параметр. В моем способе я показал как выкрутиться для старого кода.

А в предложенном вами способе разве не придется менять код вызывающего
для дополнительного обязательного параметра. А то вы тут намекаете на негибкость предложенного мною метода, а про свой, что скажете, повторяю обязательного. В вашем же случае тоже придется менять код вызывающего.
Может он все таки не такой уж и обязательный, чтобы старый Idispatch код работал?
;)


Сергей М.   (2008-10-14 20:01:00) [6]


> у меня вызывающий код ничего не проверяет


Дык о чем тогда базар ?)

Читай еще раз и внимательно:


> Как довызова f определить корректность параметров?


oxffff   (2008-10-14 19:59:00) [7]


> Сергей М. ©   (14.10.08 16:16) [37]
>
> > oxffff ©   (14.10.08 15:56) [36]
>
>
> Да нафига мне в вызывающем коде что-то проверять перед вызовом
> ?)
> Пусть этим занимается вызываемый код при вызове !
>
> Ты же, вводя в адр.строку браузера URL, не проверяешь ведь
> ее актуальность и корректность с т.з., например, наличия
> и кол-ва параметров ?
>
> Не проверяешь.
>
> И браузер тоже не проверяет - ему это тоже нафих не надо,
>  пусть проверкой занимается сам сервер.
>
> Было:
>
> someproto://somedomain/someresource?param1=A?param2=B
>
> запрос успешно выполнялся, сервер возвращал рез-т, браузер
> исправно его представлял юзеру.
>
> После того как "отцы" ресурса с какого-то бодуна взяли да
> добавили обязательный 3-й параметр при запросах к ресурсу,
>  стало:
>
> someproto://somedomain/someresource?param1=A?param2=B?param3=C
>
> А я ничего не зная об этом по-прежнему запрашиваю с 2-мя
> параметрами.
>
> Кто ответственен за возможную коррекцию моей ошибки или
> корректный отлуп запроса ?
> Разумеется, сервер (вызываемый код) ! Не браузер же (вызывающий
> код) !
> Иначе на каждый чих "отцов" придется переписывать каждый
> браузер)


Дык у меня вызывающий код ничего не проверяет. Проверяет контекст вызова сервер. Могу еще предложить вариант, где менять ничего не нужно. :)


oxffff   (2008-10-14 19:55:00) [8]


> Сергей М. ©   (14.10.08 17:22) [43]
>
> > Где я ошибаюсь?
>
>
> Этот "наследник" д.б. известен как вызывающей, так и вызываемой
> стороне.


Почему должен быть?

Если я добавил параметр, то я изменил вызываемый код.
В вызывающем коде менять ничего не нужно.

Вариант первый использование наследника базового функционала.

То есть TCallContextBase(базовый набор) и TCallContextExtended(расширенный набор), где TCallContextExtended=class(TCallContextBase) в
вызываемом коде стоит первая проверка

TCallContextBase=class
a:integer;
b:string;
end;

TCallContextExtended=class(TCallContextBase)
с:variant;
constructor create(a..,b..,c..)
end;

Вызываемая функция
function Workfunc(context:TCallContextBase):...
begin
if context is TCallContextExtended then
           else
          if context is TCallContextBase then
          begin
          //если появились какие либо обязательные параметры для старых  
          вызовов инициализируем их по умолчанию
          end
          else exit;
end;

Вызывающая функция
Workfunc(TCallContextBase.create(1,'2'))

Ничего менять не нужно для вызывающей стороны.


Сергей М.   (2008-10-14 17:32:00) [9]


> oxffff


Ключевое здесь это:

> параметры процедур в библиотеке храняться в БД


Следует понимать, что инф-ция в БД может быть изменена в любой момент времени уже послеразработки вызывающего кода, поэтому ни о каком компайл-тайм речи идти не может.
А твой подход с TCallContext и его наследниках требует именно компайл-тайм на обеих сторонах взаимодействия.


Сергей М.   (2008-10-14 17:22:00) [10]


> Где я ошибаюсь?


Этот "наследник" д.б. известен как вызывающей, так и вызываемой стороне.


oxffff   (2008-10-14 17:20:00) [11]


> Пусть этим занимается вызываемый код при вызове !


Он у меня как раз этим и занимается.


oxffff   (2008-10-14 17:18:00) [12]


> А я ничего не зная об этом по-прежнему запрашиваю с 2-мя
> параметрами.


Ну дык, а что мешет наследовать TCallContextOther  от TCallContextIntegerAndString?
Где я ошибаюсь?


Сергей М.   (2008-10-14 16:51:00) [13]


> Slym ©   (14.10.08 16:42) [39]


А как результат возвращать, если это функция ?


Slym   (2008-10-14 16:42:00) [14]

Тогда проще
type
 TProc=procedure(Params: array of const);

и типы разные и переменное число параметров


Сергей М.   (2008-10-14 16:33:00) [15]


> oxffff


В конце-концов разработчик вызываемого кода, который часто чихает, но который уважает труд разработчика вызываемого кода, предоставляет (тем или иным образом) последнему полноценную своевременно обновляемую библиотеку типов, которую можно использовать как в компайл-тайм, так и в ран-тайм.


Сергей М.   (2008-10-14 16:16:00) [16]


> oxffff ©   (14.10.08 15:56) [36]


Да нафига мне в вызывающем коде что-то проверять передвызовом ?)
Пусть этим занимается вызываемый код привызове !

Ты же, вводя в адр.строку браузера URL, не проверяешь ведь ее актуальность и корректность с т.з., например, наличия и кол-ва параметров ?

Не проверяешь.

И браузер тоже не проверяет - ему это тоже нафих не надо, пусть проверкой занимается сам сервер.

Было:

someproto://somedomain/someresource?param1=A?param2=B

запрос успешно выполнялся, сервер возвращал рез-т, браузер исправно его представлял юзеру.

После того как "отцы" ресурса с какого-то бодуна взяли да добавили обязательный 3-й параметр при запросах к ресурсу, стало:

someproto://somedomain/someresource?param1=A?param2=B? param3=C

А я ничего не зная об этом по-прежнему запрашиваю с 2-мя параметрами.

Кто ответственен за возможную коррекцию моей ошибки или корректный отлуп запроса ?
Разумеется, сервер (вызываемый код) ! Не браузер же (вызывающий код) !
Иначе на каждый чих "отцов" придется переписывать каждый браузер)


oxffff   (2008-10-14 15:56:00) [17]


> А реализацию вызывающего кода - нет.


Ведь лукавите.

Если в функции добавляется\удаляется параметр,
хотите сказать что в месте вызова не нужно его добавлять\удалять?
А как вы его хотите передать\удалить?
Придется внести изменения и в него тоже.
А в моем случае будет просто другой класс-контекст вызова.

То есть ваше
a:variant;
begin

a.SomeMethod(1,2,'222');
->
a.SomeMethod(1,2,'222',10...);


И в моем случае

TCallContextIntegerAndString.create(1,2,'222');
TCallContextOther.create(1,2,'222',10....);


Причем в моем случае проверка будет одна всего контекста вызовав целом, а вашем проверок как минимум равное количеству параметров, так что в мой велосипед все же быстрее. :)))


Сергей М.   (2008-10-14 15:55:00) [18]


> oxffff ©   (14.10.08 15:46) [34]


> с точки зрения эффективности, не самый удачный


А что делать ? Издержки интерпретации)

Хочешь универсальности и безопасности - плати за них сквозным снижением производительности..

По поводу же велосипеда - это ж не тебе было адресовано, а автору)


oxffff   (2008-10-14 15:46:00) [19]


> Сергей М. ©   (14.10.08 15:41) [32]


Этот вариант самый естественный, так же как и array of const.
Но с точки зрения эффективности, не самый удачный.
Поскольку большие дополнительные издержки.

>Т.е. ты таки движешься по пути изобретения велосипеда)

Я к счастью не Хейлсберг, но ответил бы так же как и он всегда отвечал на этот вопрос.


Сергей М.   (2008-10-14 15:44:00) [20]


> oxffff ©   (14.10.08 15:36) [31]


Реализацию вызываемого кода - да.
А реализацию вызывающего кода - нет.
Вызываемый код известит исключением вызывающий код о любом несоответсвии, будь то имя точки входа и/или кол-во/типы параметров.


Страницы:   1 2 3

Наверх

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