Вот если бы ещё динамически создавать переменные…
Да все так-же, через 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! Вообще-бы кайф был!
