Dynamic Data structures in Clarion using DynaLib

Ok up till now we havnt had time or the knowledge of runtime data structures in the clarion runtime.

With a quite winter and summer we have had a little time to look at the work of the russian in the early days of clarion 5 and 6 and re compile in clarion 11.

We have a need for this stuff in an up and coming project and i thought let publish a little of this as we go along in the next part of this project.

This is the cleaned up version of creating a queue at runtime using the russian code with some rewriting.

As we get know this code we will post tid bits of hopefully creating file and views and queues…

The statements sent to this method in the library are just simple text declarations of a queue.

This is where the queue is created and you can see the Self.Q is simple an address to a string with some data types of long , pretty simple really…we have put a window in to show the data created just for this example.

``````RTLQueueCreateClass.QConstruct PROCEDURE

DeclareMem           LONG,AUTO
QueueDeclareBuffer   &STRING
fld                 any

Window                          WINDOW('test Runtime Queue - from deep inside russia.'),AT(,,395,224),GRAY,FONT('Segoe UI',9)
BUTTON('&OK'),AT(291,201,41,14),USE(?OkButton),DEFAULT
BUTTON('&Cancel'),AT(340,201,42,14),USE(?CancelButton),STD(STD:Close)
LIST,AT(15,19,357,157),USE(?LIST1),FROM(''),FORMAT('47L(2)|M20L' & |
'(2)|M20L(2)|M')
END

Code
Clear(QueHdr)

Self.Q &= Null

! Is A Queue created here?

gSize# = Self.FSize(0,True); if gSize# < 0 then Return;end
if ~gSize# then Size# = 1 else Size# = gSize#;end
DeclareMem = RTL::NewMem(Size#); if ~DeclareMem then Return;end
QueHdr.BufferPtr = DeclareMem
QueHdr.BufferSize = gSize#

! Is GenerateDeclare

QueueDeclareBuffer &= Self.GenerateDeclare()
if QueueDeclareBuffer &= Null then
RTL::FreeMem(DeclareMem);
Return;
end

End
QueHdr.BufferPtr = OvrGrp.GPtr.BufferPtr
QueHdr.BufferSize = OvrGrp.GPtr.BufferSize
QueHdr.FieldsDefPtr = OvrGrp.GPtr.FieldsDefPtr

End
if QueueTQueueHeader &= Null ! memory allocation failed
RTL::FreeMem(DeclareMem)
else ! Set up Queue address

if ~(Self.Q &= Null)

fld &= what(self.q,1)
fld = 'data'

open(WINDOW)
?List1{prop:from} = self.Q

ACCEPT
END

close(WINDOW)

Free(Self.Q); Clear(Self.Q)
;end  ;end  ;end

QueueDeclareBuffer &= Null; QueueTQueueHeader &= Null
if ~(Self.Q &= Null)
if ~Self.Props.BStrPresent = true
Self.Props.GrpClear &= NEW(STRING(SIZE(Self.Q)))
Self.Props.GrpClear = Self.Q
else
QueueDeclareBuffer &= _NewStr(Self.Q)
Clear(Self.Q)
Self.Props.GrpClear = Self.Q
Self.Q = QueueDeclareBuffer
Dispose(QueueDeclareBuffer)
end  ;end
Self.Props.Created = True
end

Return
``````

Looks like Dynalib code.

We are going through and rewriting sections of the Russian DLIB libraries from the russians. What we found interesting was that once you have the locally declared typed groups or structures clarion database, queues and views become dynamic.

it is if that is the russian code base. We wont be taking credit for it but the code is being re worked as some of it is very very hard to read and repeats itself.

There is for a long time also a free version of Dynalib and you can contact Oleg. See https://www.clarionlife.net/novaya-versiya-dynalib-4-0-4/

1 Like

Oops, didn’t know, I delete my message then.

From the help:

Freeware Restrictions

Freeware-version of the given library has some restrictions of functionality:

The maximal size of structure up to 128 bytes
A maximal quantity of fields in a group up to 15
A maximal quantiy of keys in a file up to 2
A maximal quantity of MEMOs and BLOBs in a file up to 1
A maximal quantity of JOIN-blocks in a VIEW up to 2
A maximal quantity of levels (nests of JOIN-blocks) up to 1

These restrictions are valid both for created, and for “linked” structures. Nevertheless, I think, that not looking at these restrictions, freeware-version have sufficient functionality for their use in more - less complex projects. But if you need more flexibility with data manipulating you can purchase Professional version of DynaLib on the ClarionShop.

I dont think you will find that the product is supported any longer by the authors. Much of the code needs reworking as it not really very clean.

As we uncover it structures we are rewriting the parts we are using into a clearer to read format.

It is a very extensive library of code with a lot of functionality.

The Ukraine and Russian appear to have found and exposed all the clarion data structures and come up with a solution to runtime create all data types without using any special code except standard clarion code.

Since no work has been done on this product for what appear to about a decade we decided it was a matter of diving in and hoping the internal clarion data structures had not changed.

Much to our surprise it appear to run in clarion 11 and if clarion goes 64 we will try to support that also.

If the product is still sold on clarion shop i doubt you will get any support from the authors although we stand to be corrected on that.

As we connect the code to runtime macros i will update this thread and prehaps post some example with calc2 runtime scripts on github later in the year for clarions developers to try.

Glad all of the Russians were in on this.

Could you put some examples on GitHub? That work within the free limitation of 128 bytes.

I usually make LIST / QUEUE examples with DIRECTORY() of the Temp or Windows folder. You could take the FILE:QUEUE and copy it to a DynaLib Queue created at runtime with a STRING(32) file name. This Repo has the code to show the Temp folder in a List

1 Like

That’s pretty neat. Would be cool if there was a textbox to add our own filter criteria for the temp files for our apps that do a lot of temp files. One filter per line. And perhaps an “ignore” textbox that has a list of file masks to never make available for deletion…

e.g.

MySpecialPrefix*.tmp
OtherPrefix*.xxx

Not something I’d use every day, but it would be useful when I needed it.

This seems to be the last web scrape by the wayback machine.
Aug 2020

dLib Doc file
Wayback Machine (archive.org)

dynalib.narod.ru/freeware/dLib.zip is not in the wayback machine
dynalib.narod.ru/freeware/fScan.zip is also not in the wayback machine.

There is an extended evaluate link on the wayback machine site (last wayback machine webscrape)
“Utilities” (archive.org)

This link mentions dynalib and the TDynaFileClass class
Wayback Machine (archive.org)

The only copy of ExtEval.zip on the wayback machine
Wayback Machine (archive.org)

Found the Russian forum which looks very active still, like posts still being made today.
forum.clarionlife.net - Main page

Example of Creating a Dynamic Queue using a Proxy class.

include(‘Dynaproxycontainer.inc’),ONCE

``````MAP

module('ddynartl.clw')
CreateQueuestruct(string DataStructure,Dynaproxycontainer q),long
END

END
``````

qproxy &Dynaproxycontainer

Qflds ANY

CODE
Qflds = ‘Stockprices QUEUE,PRE(TST);’ & |
‘Code SHORT(@N_5),ALIGN®;’ & |
‘Price DECIMAL(@N13`2),ALIGN®;’ & |
‘Input DATE(@D6.B),ALIGN®;’ & |
‘Closed DATE(@D6.B),ALIGN®;’ & |
‘END;’

``````qproxy  &=  new(Dynaproxycontainer)

qproxy.IDSet.DSet('Name','META STOCK')
qproxy.IDSet.DSet('TST:Code','META')
qproxy.IDSet.DSet('TST:Price',157)

message(qproxy.IDGet.DGet('TST:Price'))

END``````

Dynamically Creating a Queue and Tables from text files.

`````` module('ddynartl.clw')
RegisterDrivers
CreateQueuestruct(string DataStructure,Dynaproxycontainer q),long
CreateFilestruct(string DataStructure,Dynaproxycontainer q),long
CreateQueuestructDeclare(string QueueName,string DataStructureFile,Dynaproxycontainer q),long
CreateFilestructDeclare(string DBFileName,string DataStructureFile,Dynaproxycontainer q),long

END

END
``````

qproxy &Dynaproxycontainer
Fproxy &Dynaproxycontainer
Qflds ANY

CODE
Qflds = ‘Stockprices QUEUE,PRE(TST);’ & |
‘Code SHORT(@N_5),ALIGN®;’ & |
‘Price DECIMAL(@N13`2),ALIGN®;’ & |
‘Input DATE(@D6.B),ALIGN®;’ & |
‘Closed DATE(@D6.B),ALIGN®;’ & |
‘END;’

``````qproxy  &=  new(Dynaproxycontainer)

qproxy.IDSet.DSet('Name','META STOCK')
qproxy.IDSet.DSet('TST:Code','META')
qproxy.IDSet.DSet('TST:Price',157)

message(qproxy.IDGet.DGet('TST:Price'))
END
RegisterDrivers

qflds = 'C:\win32clacode\Ddyna\DynaTableDatastructures.txt'
Fproxy  &=  new(Dynaproxycontainer)
``````

Files can be stored in text files for runtime declarations.

#FILE(TPSFile)

TPSFile FILE,DRIVER(‘TOPSPEED’),PRE(TPS),CREATE,Bindable
Name_Key KEY(+TPS:Name,+TPS:Desc),DUP,OPT,NOCASE
Code_Key KEY(+TPS:Code),OPT,NOCASE
Ndx_Key KEY(+TPS:Index),OPT,NOCASE,PRIMARY
Record RECORD
Name STRING(30)
Desc STRING(110)
Code LONG
Index LONG
END
END

#ENDFILE