AN> вроде этот вопрос уже поднимался, но я не могу найти: можно ли при передаче
AN> в процедуру ANY-параметра определить в процедуре его тип, т.е. чё было было
AN> передано STRING, LONG али ещё чего:AN> Пример:
AN> SomeProc PROCEDURE(? Param)
AN> code
AN> !вот здесь хочется узнать тип переданного Param и в зависимости от этого
AN> учинить определённые действия
Легально можно узнать только, что переменная, скрытая под ANY, является строкой или нет. Для получения более детальной информации необходимо уже работать непосредственно с самим UFO-обьектом, который скрыт под ANY-оберткой. Проще всего воспользоваться INTERFACE-механизмом и с его помощью использовать методы UFO-обьекта. Уже на протяжении трех версий C50/C55/C60 структура VMT для UFO-обьекта остается неизменной, что позволяет использовать единый INTERFACE для этих версий. Измениться-ли он в будущих версиях — х/з, но хочется надеятся, что нет.
Итак:
TUFO_CallInterface INTERFACE,TYPE Dummy1 PROCEDURE Dummy2 PROCEDURE Dummy3 PROCEDURE Dummy4 PROCEDURE Dummy5 PROCEDURE _Type PROCEDURE(LONG _UFOaddr),LONG Dummy6 PROCEDURE Dummy7 PROCEDURE Dummy8 PROCEDURE Dummy9 PROCEDURE Dummy10 PROCEDURE Dummy11 PROCEDURE Dummy12 PROCEDURE Dummy13 PROCEDURE Dummy14 PROCEDURE Dummy15 PROCEDURE Dummy16 PROCEDURE _Address PROCEDURE(LONG _UFOaddr),LONG Dummy17 PROCEDURE Dummy18 PROCEDURE Dummy19 PROCEDURE Dummy20 PROCEDURE _Max PROCEDURE(LONG _UFOaddr),LONG _Size PROCEDURE(LONG _UFOaddr),LONG END
Набор методов немного неполный.
Как легко заметить из описания, вызов методов несколько необычен. Т.е. реально вызов метода, например _Type, выглядит как _Type(LONG _UFOaddr,LONG _UFOaddr).
Причем предполагается, что оба параметра одинаковы. Зачем так сделано? Это связано с несколько нестандартным вариантом вызова методов UFO-обькта. О чем, кстати, я уже как-то писал в данной рассылке. В этих методах предполагается, что адрес самого обьекта передается не в EAX, а в EBX! А в EAX, кстати, некоторые методы предполагают получать один их параметров вызова! Именно поэтому остальные методы в данном описании не используются, т.к. через INTERFACE-механизм невозможно использовать EAX иначе чем для передачи адреса обьекта. Такой-же нестандартный вариант вызовов используется в Кларионе еще в нескольких обьектах. Но, как я уже писал, опять-же, в данной рассылке, в C60 работа с новыми обьектами построена уже по стандартному варианту. И с ними уже проще работать. Очевидно разработчики SV понемногу «разворачиваются» к обычным
программистам и дают возможность нам «забраться» в RTL.
Что не может не радовать!
Однако, что-то я отвлекся!
_Type - возвращает тип переменной, скрытой под ANY-оберткой. Расшифровку типов можно посмотреть в LIBSRCEQUATES.CLW _Address - возвращает адрес переменной, на которую ссылается данный UFO-обьект. _Max - возвращает кол-во элементов в текущей размерности массива. Для обычных переменных возвращает 0. _Size - возвращает размер переменной, на которую ссылается данный UFO-обьект. Для массивов возвращает ПОЛНЫЙ размер массива.
Как с этим работать?
MAP MyProc(*? _Var) END UFO &TUFO_CallInterface Var DECIMAL(11,2) Any ANY ... Any &= Var UfoAddr# = Address(Any) OMIT('***',_C55_) Peek(UfoAddr#,UfoAddr#) ! Только для C50 *** UFO &= (UfoAddr#) Type# = UFO._Type(UfoAddr#) Dim# = UFO._Max(UfoAddr#) ! Массив? if Dim# Message('Массив из '& Dim# &' элементов типа '& Type#) else Message('Переменная типа '& Type#) . MyProc(Var) ... MyProc Procedure(*? _Var) Code UfoAddr# = Address(_Var) OMIT('***',_C55_) Peek(UfoAddr#,UfoAddr#) ! Только для C50 *** UFO &= (UfoAddr#) Type# = UFO._Type(UfoAddr#) Dim# = UFO._Max(UfoAddr#) ! Массив? if Dim# Message('Массив из '& Dim# &' элементов типа '& Type#) else Message('Переменная типа '& Type#) . Return
Я показал два примера использования UFO-обьекта.
Прямо в коде программы и в процедуре.
Все абсолютно работоспособно в C50/C55/C60.