Вот если бы ещё динамически создавать переменные…
Да все так-же, через RTL Клариона!
1. Выделяем память под новую переменную.
Для этого лучше воспользоваться этими процедурами:
! Выделяет память и инициализирует ее двоичными нулями RTL::NewMem(UNSIGNED _Size),ULONG,NAME('Cla$NewMemZ') ! Выделяет память и инициализирует ее пробелами RTL::NewStr(UNSIGNED _Size),ULONG,NAME('Cla$NewMemB')
_Size — размер выделяемой памяти, определяешь сам по типу переменной.
Возвращает адрес выделенного блока памяти.
ВНИМАНИЕ!!!
Надо иметь в виду, что выделяемая память не регистрируется в RTL Клариона (напрямую берется у Виндового менеджера памяти). Поэтому эта память не будет освобождена автоматом после завершения программы. Для ее освобождения надо использовать:
RTL::FreeMem(ULONG _Addr),NAME(‘_free’)
_Addr — адрес блока памяти, полученный из предыдущих функций выделения
памяти.
Итак — память под новую переменную есть! Теперь:
2. Промежуточный этап — создание так называемой UFO-переменной. Что-то типа оболочки вокруг блока памяти, которая содержит всю необходимую информацию о перменной. Необходимо для правильной обработки новой переменной в RTL Клариона. Для этого воспользуемся такой вот функцией:
RTL::Mem2UfoAddr(ULONG _VarAddr,BYTE _VarType,ULONG _DecFloat=0, | UNSIGNED _VarSize,BYTE=0),ULONG,RAW,NAME('Cla$Mem2Ufo') _VarAddr - адрес блока памяти для новой переменной _VarType - тип создаваемой переменной Номера типов можно взять из INC-файла моей библиотеки DynaLib, фриварный вариант которой можно взять на: http://dynalIb.narod.ru Например: BYTE-1, LONG-6, DECIMAL-10, STRING-18 _DecFloat - Если создаем переменную типа DECIMAL/PDECIMAL, то здесь надо задать кол-во дробных разрядов. DECIMAL(9,2) - _DecFloat = 2 _VarSize - размер новой переменной в байтах. Для переменных типа DECIMAL/PDECIMAL он составляет ~половину от общего кол-ва цифр. DECIMAL(9,2) - _VarSize = Int(9/2)+1 = 5 С определением размеров других типов, думаю проблем не будет? Практически все это есть в доке.
Возвращает адрес созданной UFO-переменной. Если более понятно, то возвращает значение, которое, обычно, содержиться в переменных типа ANY. Ну, как и с памятью, в конце программы эти UFO-переменные надо-бы освободить, т.к. они отьедают виндовую память. И немаленькую! Для этого используем такую функцию:
RTL::FreeUfo(ULONG _UFOAddr),RAW,NAME('Cla$FreeUfo')
_UFOAddr — адрес UFO-переменной, полученный из RTL::Mem2UfoAddr() Можно, кстати, остановиться уже на данном этапе, если получать от данной функции не адрес UFO-переменной, а сразу понятный всем ANY. Для этого запишем эту функцию так:
RTL::Mem2Ufo(ULONG _VarAddr,BYTE _VarType,ULONG _DecFloat=0, | UNSIGNED _VarSize,BYTE=0),*?,RAW,NAME('Cla$Mem2Ufo')
Естественно, что освобождать такие UFO-оболочки надо уже по-другому:
Var1 ANY ... Var1 = RTL::Mem2Ufo(....) ! Создали UFO-переменную ... Var1 &= Null ! "Убили" ее
Ну, и наконец:
3. Биндим новую переменную, что-бы с ней было удобно работать. Для этого воспользуемся еще одной RTL-функцией:
RTL::Bind(ULONG _UFOAddr,STRING _Name),NAME('Cla$BindV')
_UFOAddr — адрес UFO-переменной, полученный из RTL::Mem2UfoAddr()
_Name — строковое имя новой переменной
Обращаю внимание, что _Name имеет тип ОБЫЧНОЙ STRING, а не CSTRING! И, кстати, CLIP() делать не обязательно — эта функция сама обрежет конечные пробелы. И, опять-же, как и с памятью, в конце программы не надо забыть освободить память, занятую новым именем:
RTL::UnBind(STRING _Name),NAME('Cla$UnbindV')
_Name — строковое имя освобождаемой переменной
Вот, пожалуй, и все!
Маленький примерчик. Так сказать — для усвоения темы:) Сразу предупреждаю — пример простейший и скелетный. Поэтому нет никаких проверок типа дублирования имен и пр. Предположим, есть очередь, в которой содержаться имена новых переменных, которые необходимо создать для дальнейшего использования:
MAP MODULE('Clarion RTL') RTL::NewMem(UNSIGNED _Size),ULONG,NAME('Cla$NewMemZ') RTL::NewStr(UNSIGNED _Size),ULONG,NAME('Cla$NewMemB') RTL::FreeMem(ULONG _Addr),NAME('_free') RTL::Mem2UfoAddr(ULONG _VarAddr,BYTE _VarType,ULONG _DecFloat=0, | UNSIGNED _VarSize,BYTE=0),ULONG,RAW,NAME('Cla$Mem2Ufo') RTL::FreeUfo(ULONG _UFOAddr),RAW,NAME('Cla$FreeUfo') RTL::Bind(ULONG _UFOAddr,STRING _Name),NAME('Cla$BindV') RTL::UnBind(STRING _Name),NAME('Cla$UnbindV') RTL::GetBindVar(STRING _cVarName),*?,RAW,NAME('Cla$EvaluateVariable') END END Var1 ANY sVar1 STRING(40) Var2 ANY sVar2 STRING(40) VarNamesQue QUEUE,PRE(VAR) Name STRING(40) ! Имя переменной Type LONG ! Тип Size LONG ! Размер DecFloat BYTE ! Для DECIMAL/PDECIMAL Addr LONG ! Здесь будет адрес блока памяти UFOAddr LONG ! Здесь будет адрес UFO-оболочки для переменной END ! ! Последние два поля при создании очереди инициализируются нулями. ! CODE ... Loop Var# = 1 to Records(VarNameQue) Get(VarNameQue,Var#) if ~VAR:Name OR ~VAR:Type OR ~VAR:Size then Cycle. if VAR:Type = TYPE:STRING VAR:Addr = RTL::NewStr(VAR:Size) else VAR:Addr = RTL::NewMem(VAR:Size) . if ~VAR:Addr then Cycle. ! Память не выделена VAR:UFOAddr = RTL::Mem2UfoAddr(VAR:Addr,VAR:Type,VAR:DecFloat,VAR:Size) if ~VAR:UFOAddr ! UFO-оболочка не создана RTL::FreeMem(VAR:Addr) Cycle . RTL::Bind(VAR:UFOAddr,VAR:Name) Put(VarNameQue) . Get(VarNameQue,1); sVar1 = VAR:Name Get(VarNameQue,2); sVar2 = VAR:Name Message(Evaluate(Clip(sVar1) &'+'& Clip(sVar2))) ! Var1 + Var2 ! или Get(VarNameQue,1); Var1 &= RTL::GetBindVar(Clip(VAR:Name)&'<0>') Get(VarNameQue,2); Var2 &= RTL::GetBindVar(Clip(VAR:Name)&'<0>') ! ВНИМАНИЕ!!! Если какая-либо переменная не найдена и ANY &= Null, ! без проверки на Message() получим GPF. if ~(Var1 &= Null) AND ~(Var2 &= Null) Message(Var1 + Var2) ! Var1 + Var2 .
Небольшое, но довольно важное дополнение к примеру. В конце надо освобождать за собой занятую память:
Loop Var# = 1 to Records(VarNameQue) Get(VarNameQue,Var#) if ~VAR:Addr then Cycle. RTL::FreeMem(VAR:Addr); Clear(VAR:Addr) if ~VAR:UFOAddr then Cycle. RTL::FreeUfo(VAR:UFOAddr); Clear(VAR:UFOAddr) RTL::UnBind(Clip(VAR:Name)) .
Вообщем, вот в таком вот русле. Так что, как видишь , Кларион позволяет делать очень многое из того, что другим языкам и не снилось! Надо только уметь им пользоваться.
Еще-бы, правда, более дружественное отношение разработчиков к нам — простым трудягам, а не только к приближенным 3rdParty! Вообще-бы кайф был!