Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2008.11.23;
Скачать: [xml.tar.bz2];

Вниз

Переменные процедурного типа   Найти похожие ветки 

 
checkmate-maker   (2008-10-14 12:45) [0]

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

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

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


 
clickmaker ©   (2008-10-14 12:54) [1]

а почему может возникнуть несовпадение?


 
Сергей М. ©   (2008-10-14 12:56) [2]


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


До вызова f нет никаких параметров, кроме формальных.


 
Сергей М. ©   (2008-10-14 13:01) [3]


> Функция GetPtr возвращает указатель на процедуру(либо функцию)


Делай так

type
 TMyProc = procedure(a0: Integer; a1:String); stdcall;
var
f: TMyProc;

function GetPtr(): TMyProc;

и ни о чем не задумывайся - чуть что не так, умный компилятор тут же даст по рукам)


 
Slym ©   (2008-10-14 13:08) [4]

Я чищу зубы... как мне удостовериться что я в рот засунул щетку а не строл дробовика? И что это за странный рычажок на моей щетке?


 
checkmate-maker   (2008-10-14 13:22) [5]


> Я чищу зубы... как мне удостовериться что я в рот засунул
> щетку а не строл дробовика? И что это за странный рычажок
> на моей щетке?


К сожалению щетки производишь не ты. Не стоит быть уверенным в том, что  параметры щетки постоянны во времени - может и выстрелить.


 
checkmate-maker   (2008-10-14 13:25) [6]


> Сергей М.

 Спасибо, Сергей. Но хочу уточнить, реальная ситуация диктует, что функция GetPtr параметризована(мои извинения, что не обрисовал это сразу), возвращает указатели на разные процедуры(функции) - Что делать в этом случае?


 
Slym ©   (2008-10-14 13:31) [7]

checkmate-maker   (14.10.08 13:25) [6]
я застрелил тебя из щетки


 
clickmaker ©   (2008-10-14 13:40) [8]

> функция GetPtr параметризована(мои извинения, что не обрисовал
> это сразу), возвращает указатели на разные процедуры(функции)

каждый раз с разным числом параметров?


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


> checkmate-maker   (14.10.08 13:25) [6]


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


 
checkmate-maker   (2008-10-14 14:04) [10]


> каждый раз с разным числом параметров?

Совершенно верно. По сути дела в зависимости от параметра возвращает разные процедуры. Например если параметр = 0, то это процедура без параметров, если = 1, то с одним. Понимаю, что в зависимости от параметра следует использовать разное объявление переменной f, но хочется подстраховаться перед вызовом f, хочется знать, на процедуру с каким числом и каких параметров воззвращен указатель.
 Надеюсь, большой текст не затуманит мысль.
 Спасибо.


 
clickmaker ©   (2008-10-14 14:09) [11]

> Например если параметр = 0, то это процедура без параметров,
> если = 1, то с одним

заведи массив указателей на процедуры
параметр сделай индексом в нем


 
oxffff ©   (2008-10-14 14:22) [12]


> возвращает указатели на разные процедуры(функции) - Что
> делать в этом случае?


Контракт этих процедур совпадает?


 
Сергей М. ©   (2008-10-14 14:24) [13]


> хочется подстраховаться перед вызовом f


А чего собственно ты боишься, коли о страховке задумался ?


 
checkmate-maker   (2008-10-14 14:37) [14]


> А чего собственно ты боишься, коли о страховке задумался
> ?


Интерфейс процедур в библиотеке меняется чуть реже, чем заходит солнце. Сложно быть уверенным в том, что завтра у процедуры в библиотеке не добавиться/убавиться еще один параметр, измениться тип. Хочется отловить эту ситуацию.
 Пока, чувствую, самое верное из форума - это фраза:

> Возвратив pointer ты сознательно "обезличил" подпрограмму.

 Видимо, придется пользоваться try..except.


 
oxffff ©   (2008-10-14 14:41) [15]


> По сути дела в зависимости от параметра возвращает разные
> процедуры. Например если параметр = 0, то это процедура
> без параметров, если = 1, то с одним. Понимаю, что в зависимости
> от параметра следует использовать разное объявление переменной
> f, но хочется подстраховаться перед вызовом f, хочется знать,
>  на процедуру с каким числом и каких параметров воззвращен
> указатель.


Этот подход совершенно не выразителен и небезопасен.
Если возвращаемые функции известны в Compile time, то тебе нужно сделать

TGetProc<T>=function GetProc(idx:integer):T;
TMyProc2 = procedure(a0: Integer; a1:String); stdcall;
TMyProc3 = procedure(a0: Integer; a1:String;a2:String;); stdcall;

a:TGetProc<TMyProc2>;
a:TGetProc<TMyProc3>;
begin

//Сделать жесткое присваивание.
Честно говоря не пробовал но Barry использует "очень жесткое" при generics.Collections, а точнее
a:= @GetPtr
b:=@GetPtr

a(2)(1,"2")
b(3)(1,"2","3")

Надеюсь идею понял. :)


 
oxffff ©   (2008-10-14 14:46) [16]


> checkmate-maker   (14.10.08 14:37) [14]


В таком случае при изменении контракта тебе лучше использовать другой вариант. По аналогии с анонимным методом.
Параметры из объекта окружения, так называемый функтор.

UnyCall=class
procedure UnyCall;virtual;abstract;
end;

UnyCall2=class(UnyCall)
protected
a:integer;b:string;
procedure UnyCall;virtual;abstract;
constructor (a:integer;b:string);
procedure UnyCall;override;
end;

constructor (a:integer;b:string);
begin
self.a:=a;
self.b:=b;
end;

procedure UnyCall;override;
begin
use A,b here
end;

Вызов такой.

var a:UnyCall;

a:=UnyCall2.create(1,"2")

a.unycall();
...

Идея понятна?


 
oxffff ©   (2008-10-14 14:47) [17]


> a:TGetProc<TMyProc2>;
> a:TGetProc<TMyProc3>;


> a:TGetProc<TMyProc2>;
> b:TGetProc<TMyProc3>;


 
Сергей М. ©   (2008-10-14 14:50) [18]


> Видимо, придется пользоваться try..except


Это не обезопасит, а только усугубит последствия.
Исключение ты, возможно, и поймаешь, но при этом нет никакой гарантии, что код, вызвавший исключение, не натворил непоправимых бед в АП процесса.

Может быть, есть резон обратить взор на ole-автоматизацию и диспинтерфейсы ?


 
oxffff ©   (2008-10-14 14:51) [19]


> Честно говоря не пробовал но Barry использует "очень жесткое"
> при generics.Collections.defaults, а точнее


cм.
Generics.Defaults;

функция создания объекта нештатными средствами.
function MakeInstance(vtable: Pointer; sizeField: Integer): Pointer;


 
oxffff ©   (2008-10-14 14:58) [20]

Могу еще предложить вариант

IGetParameterCallBack=interface
function GetParameter(idx:integer,var param):boolean;
end;

TUnyProc=function (const GetParameter:IGetParameterCallBack):integer;

function MyProc(const GetParameter:IGetParameterCallBack):integer;
var a:integer;
    b:string;
begin
if not GetParameter.GetParameter(1,a) then showmessage("No params");
if not GetParameter.GetParameter(2,b) then showmessage("No params");
....
end;


 
Сергей М. ©   (2008-10-14 14:58) [21]


> oxffff


Какие контракты, какие функторы ?
Ты сейчас с кем разговариваешь ?)
У человека D7, а ты ему про функторы да про сфинктеры)


 
checkmate-maker   (2008-10-14 15:00) [22]


> Параметры из объекта окружения, так называемый функтор.


> Идея понятна?

Спасибо, но непонятно как связать построенную Вами ООМ c моей задачей.
Объявлять методы в одном классе, а реализовывать в его наследниках я, к счастью, умею.
Спасибо за термин "функтор"  - почитаю.


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


> Сергей М. ©   (14.10.08 14:58) [21]


oxffff ©   (14.10.08 14:46) [16]
oxffff ©   (14.10.08 14:58) [20]

Штатно реализуются в D7.

P.S. Жаль что вы только про сфинкторы знаете. :)


 
Сергей М. ©   (2008-10-14 15:09) [24]


> oxffff ©   (14.10.08 15:00) [23]

Я про [15])


 
oxffff ©   (2008-10-14 15:10) [25]


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


А...
Дык я стараюсь не ограничиваться одним вариантом решения. :)


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


> checkmate-maker   (14.10.08 15:00) [22]


Проверку на соответствие кол-в и типов ожидаемых и фактически переданных параметров можно отдать на откуп любому готовому механизму маршаллинга диспинтерфейсных вызовов. При несовпадении он возбудит соответствующее исключение.


 
oxffff ©   (2008-10-14 15:23) [27]


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


Могу упростить решение до минимума.

TCallContext=class
end;

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

procedure Myfunc(a:TCallContext);
begin
if a is TCallContextIntegerAndString then
 else
 begin
 Showmessage("Not valid context");
 exit;
 end;
end;


 
checkmate-maker   (2008-10-14 15:29) [28]

Спасибо Всем за участие в дискуссии.
Воспользоюсь тем, что параметры процедур в библиотеке храняться в БД(об этом я промолчал намеренно - без обид), создам фунцию, следующего вида
function MayConnectToFunc(aFuncIdent: WideString; aParamArray: array of String; aIsFunc: Boolean = False): Boolean;
здесь aFuncIdent - точка входа в процедуру(параметр, который я использую при вызове GetPtr, описанный выше);
aParamArray - массив с типами параметров в согласовании с порядком следования; Также можно использовать TStringList.
aIsFunc-флажок, что это функция и последнее значение в массиве - это тип возвращаемого значения.


 
Сергей М. ©   (2008-10-14 15:32) [29]


> oxffff ©   (14.10.08 15:23) [27]


Не пойдет.
При любом чихе править придется и вызываемую и вызывающую сторону.


 
oxffff ©   (2008-10-14 15:33) [30]


> checkmate-maker   (14.10.08 15:29) [28]


Главное, чтобы работало. :)


 
oxffff ©   (2008-10-14 15:36) [31]


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


Дык, и в вашем случае тоже самое.
В любом случае при расширении функции придется менять ее реализацию и место вызова. Хотите сказать что в вашем случае не так?


 
Сергей М. ©   (2008-10-14 15:41) [32]


> checkmate-maker   (14.10.08 15:29) [28]


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

Тогда уж, чтобы меньше возни было и для пущей универсальности:

function CallProcByName(AProcName, AParams: OleVariant): OleVariant; safecall;


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


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


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


 
oxffff ©   (2008-10-14 15:46) [34]


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


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

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

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


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


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


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


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

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

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


 
oxffff ©   (2008-10-14 15:56) [36]


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


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

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

То есть ваше
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 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-мя параметрами.

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


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


> oxffff


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


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

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

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


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


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


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



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

Форум: "Начинающим";
Текущий архив: 2008.11.23;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.007 c
4-1200394661
Lamer666
2008-01-15 13:57
2008.11.23
Как организовать таймер в программе без формы?


2-1223561075
dmitry_12_08_73
2008-10-09 18:04
2008.11.23
Посветка SPeedButton


15-1222450529
No_Dead(work)
2008-09-26 21:35
2008.11.23
зачем нужен *.ion?


1-1202298317
Виталий
2008-02-06 14:45
2008.11.23
ПРоблема с ТListView


1-1202278974
Karburator
2008-02-06 09:22
2008.11.23
событие OnColWidthsChanged в компоненте TDBGrid





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский