Архив рубрики: Статьи Руденко Олега

Так что, Size() — это обычная рантаймовская ф-ия?

NT> Так что, Size() — это обычная рантаймовская ф-ия? Я полагал, что эта ф-ия NT> вычисляется компилятором:
NT> «SIZE Supplies the amount of memory used for storage. NT> variable The label of a PREVIOUSLY DECLARED variable. NT> […] NT> SIZE directs the COMPILER to supply …»

Все правильно — Size() это не рантаймовская функция, но компилятор обрабатывает ее интеллектуально а не просто вычисляет на этапе компиляции. Если мы просим дать нам размер переданной в процедуру строки, то компилятор в качестве результата Size() подставляет значение внутренней переменной, в которой хранится длина переданной в процедуру строки. То-же касается и рефералов на строки/группы/очереди/классы — компилятор генерит код, который «вытаскивает» из этих рефералов нужное значение.

Так что, в доке — немного неполная инфа по Size(). И можно, с некоторой натяжкой, считать, что Size() — это рантаймовская функция в виде online-кода.

Вместо процедур клары PEEK, POKE можно использовать…

АА> !  Вместо процедур клары PEEK, POKE
АА> !  можно использовать
АА> !
АА> !  MoveMemory(Long adrto,long adrFrom,long
АА> ! sz),bool,proc,pascal,name('RtlMoveMemory')
АА> !
АА> !  1-параметр адрес куда записывается
АА> !  2-параметр адрес куда пишется
АА> !  3-размер копируемых данных
АА> !
АА> !  Александр Бирюков
АА> Очень интересно! А ты не пробовал посмотреть эту ф-ю на ассемблерном уровне?
АА> Это одна asm-команда копирования строки (через запись адресов и длины в
АА> регистры) или они побайтно копируют? Для меня это очень актуально (надо
АА> поднять скорость приложения, а оно по большей части именно память с места на
АА> место копирует).
АА> И как у этой ф-ии с совместимостью между версиями? И как она представлена в
АА> разных режимах линковки (Local/Stand..)?

Делать замену операторов PEEK()/POKE() имеет смысл только для структур или массивов. Так как для стандартных типов BYTE-LONG, компилятор заменяет эти операторы на одну-две асм-инструкции.

И если уж делать их замену, то лучше вместо предложенной API-шной функции Читать далее

Как узнать адрес начала и конца КОДА процедуры?

Адрес начала — Address(Proc).
Адрес конца — сомневаюсь. Если в модуле, где сидит данная прога есть инфа о длине проги, то тогда понятно, как определить адрес конца (проги). Хотя, сомневаюсь, что такое кто-нибудь делает.

Правда, исследуя недра Клариона, могу сказать, что в подавляющем большинстве процедур, есть только ОДИН выход через RET NEAR. И обычно всегда — в конце кода процедуры. По крайней мере, я иных не встречал. Хотя допускаю их наличие.
Так что, можно просканировать память с адреса начала процедуры и до нахождения кода оператора RET NEAR. Это и будет, с большой вероятностью, адрес конца кода данной процедуры.
Кстати, все процедуры в Кларионе завершаются именно оператором RET NEAR xx. Даже процедуры из внешних DLL-библиотек. Для вызова таких процедур Кларион эмулирует «дальний» вызов с помощью дополнительной локальной процедуры с одним оператором JMP _DllProc. Читать далее

Перебираю поля группы циклом. Как мне отличить корректные значения AnyVar от некорректных?

YF> Перебираю поля группы циклом.Для каждого поля
YF>     AnyVar &= What(Group,FiedlNo)
YF> Как мне отличить корректные значения AnyVar от некорректных?
YF> Дело в том, что если поле имеет совсем неподходящий тип
YF> (массив или ссылка), присваивание всё равно срабатывает,
YF> но Any-переменная ни к чему не пригодна.
YF> Вопрос, скорее всего, к Олегу Руденко….

Когда поле описано как ссылка, то What() и вернет значение этой ссылки. Значение ИМЕННО самой ссылки, а не переменной, на которую указывает эта ссылка! Дело в том, что все ссылки в группе описаны одним общим типом REFERENCE(1Fh). Отличаются они только размером, который также передается в ANY. Если известен тип ссылки (тогда зачем What()?:)), то довольно легко получить и значение переменной, на которую Читать далее

BLOB

Олег А. Руденко

Hello, Robert.

If you are not afraid to use undocumentary possibilities of the language, then look in an attach. I have corrected your example slightly. Now it works how you wanted. My corrections are marked as «Corrections by Oleg A. Rudenko».

Briefly I shall explain:

The reference on BLOB represents group of two fields:

BLOBRef        GROUP
ParentFile       &FILE
BlobNo            SHORT
               END

This feature has allowed to realize your idea! Читать далее

Все больше и больше убеждаюсь, что Кларион очень похож на своего родителя — С.

Все больше и больше убеждаюсь, что Кларион очень похож на своего родителя — С. При некоторой сноровке можно сделать практически все, что может С, но при этом, как и в С, надо быть очень осторожным!

Итак.
Казалось-бы вполне стандартная и документированная декларация функции:

1.  Tst(),*STRING,PROC

Т.е., функция возвращает указатель на строку (&STRING), но при этом допускается вызывать ее как обычную процедуру, без приема возвращаемого результата. В общем — ничего необычного. Читать далее

Еще один новый недокументированный тип

Если кто помнит, в предыдущем письме а писал, что в Кларе «обнаружился» новый тип переменной размером в 16 байт. Так вот, компилятору этот тип известен под именем VARIANT. Не знаю, есть ли он в предыдущих версиях, но в С5 уже есть.

NewVar  VARIANT

Он представляет собой, если можно так сказать, симбиоз двух типов — ANY и BSTRING. Позволяет присваивать любые значения. При этом строки хранит, как и BSTRING, в юникоде. При присваивании чисел не преобразует их в строку, как BSTRING, а хранит, как и ANY, в числовом виде. Надо иметь ввиду, что переменные типа ULONG предварительно преобразуются в REAL. Также преобразуются в REAL и DECIMAL-переменные. Заметьте, что при этом будут утеряны дробные разряды старше 15-го. При обратном присваивании числовым переменным значение из VARIANT всегда преобразуется в REAL. В этом плане поведение аналогично ANY-переменным.

Но, в отличии от ANY, не позволяет присваивать рефералы на переменные. Хотя компилятор генерит необходимый для этого код с привлечением функций ядра по работе с типом VARIANT. Так что, очевидно, существуют особые ситуации, когда такое присваивание возможно. Или в данной версии еще не полностью проработан данный тип.

Надо заметить, что в некоторых случаях для работы с переменными этого типа используются функции из OLE-библиотеки. Так что, возможно, этот тип и предназначен, в основном, для работы с OLE-обьектами.

Вот, в принципе, и все о новом типе.

Кстати!
У файла также «обнаружился» новый атрибут — CDROM. Драйвер его опознает, но что он означает — обнаружить не удалось. Но точно не READONLY, как можно было бы предположить!

Multylanguage base

VS> А вот что с Clarion’oм делать? Ждать документирования BString? Или попробовать ее заюзать?

А чего ждать? Я, кажется, недавно описывал суть, возможности и способы использования строк этого типа. На всякий случай, напомню:

  • строки данного типа представляют собой хранилища данных в юникоде динамического размера.
  • при присваивании значения такой строке, сначала освобождается ранее занятая ею память (если уже была инициализация), после чего выделяется новый блок памяти размером, как минимум, равным удвоенной длине нового значения + 4(2 для 16-бит) байта для длины.
  • при записи нового значения в выделенную память происходит конвертация обычного ANSI-текста в юникод.
  • при считывании значения такой строки автоматом происходит обратная конвертация юникода в ANSI-текст.
  • до первого присваивания поле такого типа содержит нулевой указатель, что, впрочем, не приведет к ошибке при операции типа: Str = BStr, т.к. функции ядра по манипулированию данными в стеке корректно обрабатывают нулевые указатели.

Т.е., само по себе такое поле представляет Читать далее

Буфер записи (top secret) #2

VY> PS.
VY> А вот еще интересный момент, как например сработать «указатель» на буфер записи по аналогии с C55. То есть, чтоб некоторая процедура позволяла получить его как &GROUP (без магического обрамления в группу).
VY> C55:
VY> RecPtr &GROUP
VY> ….
VY> RecPtr &= MyFile{PROP:Record}
VY> C5:
VY> RecPtr &GROUP
VY> ….
VY> А здесь процедура должна этот RecPtr «указать».
VY> У меня получилость только так (с обрамлением):
VY> !********************
VY> FRecGrp       GROUP
VY> FRecord         &GROUP
VY>              END
VY>  CODE
VY>  GetFileRecord(TestFile, FRecGrp)
VY> ! Теперь FRecGrp.FRecord — то что нам надо.
VY> !********************
VY> GetFileRecord PROCEDURE(FILE MyFile, *GROUP RecGrp)

Иначе и не получиться. Я уже писал про то, что компилятор не позволяет вернуть из функции указатель на группу. Даже в С55. Новое свойство {PROP:Record} просто исключение, которое по особому обрабатывается компилятором.

У меня, вообще, есть подозрение, что компилятор знает как обрабатывать каждое свойство! Т.е., вместо того, чтобы сделать универсальный механизм свойств объекта, которые обрабатываются исключительно внутренними методами объекта без вмешательства компилятора, разработчики опять «намудрили»! Сами свойства, как и положено, обрабатываются внутренним механизмом объекта: у файла/View — драйвером файла, у контролов окна — методами класса контрола. Но вот насчет возвращаемого значения — тут опять работает компилятор. Если, например, написать дополнительный драйвер объекта, который будет обрабатывать дополнительные свойства, то в большинстве случаев ничего путного из этого не получиться. Компилятор просто не будет знать, что делать с возвращаемым результатом. Так что, увы, пока у разработчиков не получился универсальный механизм работы со свойствами объектов.

Кстати, Владимир. Ты спрашивал насчет моих писем. Обычно все письма насчет внутренней работы Кларион шли с заголовками типа: «Внутренняя реализация Клариона» и «Некоторые особенности при работе с …» Вместо точек — GROUP/QUEUE/FILE/VIEW/CLASS.

Обычно я их слал в оба списка рассылки. К сожалению, в отличие от списка clarion@yahoogroups.com, у данного списка нет архива писем. По крайней мере, на сайте АРСИСа я не видел никакого упоминания на этот счет. А жаль! Было бы неплохо, если бы такой архив был в данном списке.

P.S. В предыдущем письме я спрашивал — не знает ли кто как можно передавать в функцию указатели на НЕИМЕНОВАННЫЕ классы и возвращать из функций указатели на них. Так вот, если кому интересно — мне удалось это сделать. Правда, возврат получается немного некрасиво, типа:

MyClass &= Address(GetClassRef())

Зато — работает. И не надо предпринимать какие-либо специальные меры, типа помещения данного указателя в группу.

Буфер записи (top secret)

VY> С5ee-b
VY> Неоднократно уже поднимался вопрос,
VY> как зная только метку файла получить доступ к буферу записи.
VY> Неоднократно давались
VY> ответы, примерно так:
TestProc PROCEDURE(*FILE MyFile)
FileHeader GROUP
DriverPtr ULONG !указатель на точку входа драйвера файла
NamePtr &STRING !указатель на строку именифайла (так можно только в 32-бит)
DrvInitPtr &STRING !указатель на строку инициализации драйвера (так можно только в 32-бит)
PasswordPtr &STRING ! указатель на строку пароляфайла (так можно только в 32-бит)
Status BYTE ! атрибуты файла
KeyCount BYTE !количество ключей
MemoCount BYTE !количество MEMO-полей
RecordSize ULONG !размер записи (буфера записи)
FieldsDefPt ULONG !адрес структуры описания полей записи файла 
KeysDefPtr ULONG ! адрес структуры описания ключей файла
MemosDefPtr ULONG ! адрес структуры описания MEMO-полей
RecordPtr &GROUP !указатель на буфер записи 
         END

???? Это где-же ты такое нашел?
RecordPtr      ULONG
Только ТАК и никак иначе!!! А как составить из этого правильный указатель на запись см. в конце письма.

А в 16 бит не только указатели на строки меняются на простые LONG, но и все размеры задаются через SHORT. Читать далее