Информационный сервер для программистов: Исходники со всего света. Паскальные исходники со всего света
  Powered by Поисковый сервер Яndex: Найдется ВСЁ!
На Главную Исходники Форум Информер Страны мира
   Приемы Вызова Программ    >>    addrcall
   
 
 Вызов процедур по адресу  Василий Рабец 11.03.1993

Простейший способ вызова процедуры по ее адресу в Turbo Pascal'е.



2k 
 

From: Василий Сергеевич Рабец <rabets@icph20.sherna.msk.su> Subj: Простейший способ вызова процедуры по ее адресу в Turbo Pascal'е. Date: 11.03.93 (C) V.S.Rabets, 1993. Простейший способ вызова процедуры по ее адресу в Turbo Pascal'е. В Turbo Pascal'е нередко встречается такая ситуация: указатель P содержит адрес некоторой процедуры без параметров; нужно вызвать эту процедуру. Обычно в таком случае используется оператор asm (начиная с TP 6.0): asm call dword ptr P end или inline: inline ($FF/$1E/>P); {call dword ptr [>P]} К сожалению, вызвать процедуру, приведя тип pointer к типу procedure procedure (P) не удастся - компилятор воспримет такую конструкцию как ошибку. Однако можно (и это самый простой путь) объявить, например, тип type ExecPtr = procedure; и вызвать процедуру ExecPtr (P); что короче и проще, чем asm и inline, и не требует знакомства с ассемблером. *** КОНЕЦ основного текста. Дальше идут примеры и комментарии *** (* Вообще не совсем понятно, почему для хранения адреса процедуры обычно используется переменная типа pointer, а не procedure. Единственный недостаток procedure - некоторые сложности с созданием типизированных констант (2 строки вместо одной): const NilPtr: pointer = nil; var P: procedure absolute NilPtr; Преимущество procedure - компилятор следит за соответствием типов (например, в нашем примере - чтобы переменной P при- сваивалось значение только процедуры типа far без парамет- ров); для переменной типа pointer никакого контроля нет. *) =================================================================== Ниже приведены примеры программ с использованием всех вышеупомяну- тых способов вызова процедуры по ее адресу. Каждый пример содержит создание типизированной константы с нулевым значением; присвоение ей некоторого значения, в т.ч. нулевого; проверку, не является ли значение переменной нулевым; вызов процедуры по адресу, сохраненному в переменной. Exe - файлы во всех случаях получаются совершенно одинаковыми; исходный текст проще в примере с использованием типа ExecPtr. -------------------------------------------------- program _Asm; { Пример вызова процедуры по адресу, сохраненному в переменной типа pointer, оператором asm. } uses CRT; const P: pointer = nil; procedure Proc1; far; begin writeln(#7) end; procedure Proc2; far; begin writeln(#7#7) end; begin writeln ('1 or 2 ?'); case ReadKey of '1': P:=@Proc1; '2': P:=@Proc2; else P:=nil end; {of case} if P<>nil then asm call dword ptr P end; end. -------------------------------------------------- program _Inline; { Пример вызова процедуры по адресу, сохраненному в переменной типа pointer, оператором inline. } uses CRT; const P: pointer = nil; {$F+} procedure Proc1; begin writeln(#7) end; procedure Proc2; begin writeln(#7#7) end; {$F-} begin writeln ('1 or 2 ?'); case ReadKey of '1': P:=@Proc1; '2': P:=@Proc2; else P:=nil end; {of case} if P<>nil then inline ($FF/$1E/>P); {call dword ptr [>P]} end. -------------------------------------------------- program _ExecPtr; { Пример вызова процедуры по адресу, сохраненному в переменной типа pointer, приведением к типу ExecPtr. } uses CRT; type ExecPtr = procedure; const P: pointer = nil; {$F+} procedure Proc1; begin writeln(#7) end; procedure Proc2; begin writeln(#7#7) end; {$F-} begin writeln ('1 or 2 ?'); case ReadKey of '1': P:=@Proc1; '2': P:=@Proc2; else P:=nil end; {of case} if P<>nil then ExecPtr (P); end. -------------------------------------------------- program _Procedure; { Пример вызова процедуры по адресу, сохраненному в переменной типа procedure. } uses CRT; const NilPtr: pointer = nil; var P: procedure absolute NilPtr; {$F+} procedure Proc1; begin writeln(#7) end; procedure Proc2; begin writeln(#7#7) end; {$F-} begin writeln ('1 or 2 ?'); case ReadKey of '1': P:=Proc1; '2': P:=Proc2; else @P:=nil end; {of case} if @P<>nil then P; end. --------------------------------------------------------------- 11-03-93 В.С. Рабец e-mail: rabets@icph20.sherna.msk.su Адрес: 142 432 Московская обл. Ногинский р-н п. Черноголовка Школьный б-р, 18, кв. 241 Рабцу В.С.