Updated 2012-01-06 13:06:40 by dkf

NJG May 24, 2006

This is a follow-up to Yet another dll caller. Since I have put that page to this wiki I have, as it always happens, discovered some bugs in and some shortcomings of the code.

Now in the package that can be fetched from the original page you will find

  • both a dll caller for Windows (dll.dll) and an so caller (dll.so) for Linux, as well as
  • an example script (text2photo.tcl) that uses the freetype library (freetype6.dll or libfreetype.so.6.3.8) for converting plain text into a photo image.

As to the latter, whether under Windows or Linux, you unzip the package into a directory and run the script with wish in that directory. (Be warned though, if you want to understand what goes on in the script you should first read the freetype2 tutorial!)

The still missing major functionality is the abilty to code the body of callback functions in Tcl. Will be coming (not so) shortly.

In the meantime I have enhanced the ::dll::memrd command, which still have two parameters, <address pattern> and <data pattern> (in that order), but they now have a more complex syntax.

The idea occured to me while writing a script that converted OpenOffice text documents into docbook format. The OpenOffice documents are zip archives that contain a number of xml files and graphical objects, thus in the script I was heavily using the functions exported by the libxml2 library. Working in a DOM tree and using XPath expressions it became a routine task of fetching arrays of values reached through a chain of pointers embedded into structures. Moreover, it frequently happend that the number of values to be fetched were to be found in one of the structures along the chain.

In the somewhat hackish syntax for <address pattern> the sequence n> (where n is an integer or anything that evaluates to an integer) means that add n to the current address value and make the content at this address become the new current address (i.e. follow the pointer we found there). If we assume that we start from address 0 then we can define a target address that can be reached through a chain of pointers with a series of such sequences (of which the last may be only a number meaning that after the addition we get the address). If the number is zero in the sequence it may be left out. A nonzero starting address can be specified by the number| (vertical bar) sequence at te very beginning of the patttern.

In the pattern there may also be at most one occurence of a number letter sequence where letter maybe c, s or i. It says that the char, short or integer value at offset number from the current address gives the number of elements to be fetched starting at the targe address. This operation, however, does not change the current address!

The pattern ${var}|4>12s>-5 thus reads: start at the address held in variable var, add 4 to it and follow the pointer found there, save the 16-bit value at offset 12 from the current address as the number of elemets to be fetched then follow the pointer at he current address, finally subtract 5 from the current address to get the final target address.

If the array at the target address contains pointers that lead (possibly through a pointer chain) to the elements we are really interested in, then we separate the two descriptive patterns with an ! (exclamation mark).

Expanding the previous example: ${var}|4>12s>-5!>7>. Until the ! we do as above. Then we iterate over the array at each step starting with the content of the array element then following the chain specified by the second part of the pattern.

The type of the elements to be returned is determined by <data pattern>. c, s, i stand for integer values of different size, - or < for srings (for compatibility reasons -1 is also accepted). No type specifier requests bytearray: number gives the length in bytes, NULL (missing) -> length spec is part of the bytearray. If there is no length specification in the address pattern the length may be given by preceeding the type specifier with a number (but not for bytearrays).

If more than a single value is fetched then ::dll::memrd returns a list.

One more fact: whatever I develop in/for Tcl is never intended to be a product on its own right, rather they are utilities/tools that help me in my everyday work. So they are always a "work in progress" (i.e. tested only to the extent they are used.) So squeak if you are hurt. I may be of help.

In the "will be coming" features, asynchronous callbacks ?